blob: 6fe601bb6113b2a413383ca976a2b9ec35a53a25 [file] [log] [blame]
developer05f3b2b2024-08-19 19:17:34 +08001From 1a9b003e08a15df0e52604b991c1dd851a9bd265 Mon Sep 17 00:00:00 2001
2From: Shayne Chen <shayne.chen@mediatek.com>
3Date: Fri, 19 Jul 2024 15:26:42 +0800
4Subject: [PATCH 010/126] sync 2024-08-13 openwrt/trunk patches folder
developer66e89bc2024-04-23 14:50:01 +08005
developer05f3b2b2024-08-19 19:17:34 +08006Sync to e80520197c9ca7bced50d3605d6baba6dead6e35
7"hostapd: Add support for APuP"
8
9Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
developer66e89bc2024-04-23 14:50:01 +080010---
developer05f3b2b2024-08-19 19:17:34 +080011 hostapd/Makefile | 153 +-
12 hostapd/config_file.c | 42 +-
developer66e89bc2024-04-23 14:50:01 +080013 hostapd/ctrl_iface.c | 4 +
14 hostapd/defconfig | 15 +-
15 hostapd/hostapd_cli.c | 10 +-
16 hostapd/main.c | 21 +-
17 src/ap/acs.c | 5 +-
18 src/ap/airtime_policy.c | 15 +-
developer05f3b2b2024-08-19 19:17:34 +080019 src/ap/ap_config.h | 37 +
20 src/ap/ap_drv_ops.c | 28 +-
21 src/ap/ap_drv_ops.h | 24 +-
22 src/ap/apup.c | 168 +
23 src/ap/apup.h | 24 +
24 src/ap/beacon.c | 16 +-
developer66e89bc2024-04-23 14:50:01 +080025 src/ap/ctrl_iface_ap.c | 45 +-
26 src/ap/dfs.c | 22 +-
27 src/ap/drv_callbacks.c | 16 +-
developer05f3b2b2024-08-19 19:17:34 +080028 src/ap/hostapd.c | 59 +-
29 src/ap/hostapd.h | 41 +
developer66e89bc2024-04-23 14:50:01 +080030 src/ap/hw_features.c | 3 +-
developer05f3b2b2024-08-19 19:17:34 +080031 src/ap/ieee802_11.c | 55 +-
32 src/ap/ieee802_11.h | 2 +
developer66e89bc2024-04-23 14:50:01 +080033 src/ap/ieee802_11_ht.c | 15 +
developer66e89bc2024-04-23 14:50:01 +080034 src/ap/ieee802_11_vht.c | 17 +
35 src/ap/ieee802_1x.c | 6 +
developer05f3b2b2024-08-19 19:17:34 +080036 src/ap/rrm.c | 10 +
developer66e89bc2024-04-23 14:50:01 +080037 src/ap/sta_info.c | 35 +-
developer05f3b2b2024-08-19 19:17:34 +080038 src/ap/sta_info.h | 16 +-
39 src/ap/ubus.c | 15 +
40 src/ap/ubus.h | 5 +
41 src/ap/ucode.c | 17 +
42 src/ap/ucode.h | 4 +
developer66e89bc2024-04-23 14:50:01 +080043 src/ap/vlan_full.c | 4 +
44 src/ap/vlan_init.c | 8 +-
45 src/ap/wnm_ap.c | 16 +-
46 src/ap/wpa_auth.c | 3 +-
47 src/ap/wpa_auth_glue.c | 9 +-
48 src/ap/wps_hostapd.c | 6 +-
49 src/ap/x_snoop.c | 22 +-
developer05f3b2b2024-08-19 19:17:34 +080050 src/common/defs.h | 4 +
developer66e89bc2024-04-23 14:50:01 +080051 src/common/dpp_crypto.c | 10 +-
52 src/common/hw_features_common.c | 1 +
53 src/common/ieee802_11_defs.h | 2 +
54 src/common/sae.c | 7 +
developer66e89bc2024-04-23 14:50:01 +080055 src/common/wpa_ctrl.c | 10 +-
56 src/crypto/Makefile | 129 +-
57 src/crypto/crypto_mbedtls.c | 4228 +++++++++++++++++++++
58 src/crypto/crypto_module_tests.c | 134 +
developer66e89bc2024-04-23 14:50:01 +080059 src/crypto/tls_mbedtls.c | 3313 ++++++++++++++++
developer05f3b2b2024-08-19 19:17:34 +080060 src/drivers/driver.h | 38 +-
61 src/drivers/driver_nl80211.c | 174 +-
developer66e89bc2024-04-23 14:50:01 +080062 src/drivers/driver_nl80211_capa.c | 4 +
63 src/drivers/driver_nl80211_event.c | 5 +
64 src/drivers/driver_nl80211_scan.c | 2 +-
65 src/drivers/drivers.c | 4 +
66 src/drivers/drivers.mak | 4 +-
67 src/drivers/rfkill.h | 16 +
68 src/radius/radius_client.c | 34 +
69 src/radius/radius_client.h | 2 +
70 src/radius/radius_das.c | 201 +-
71 src/radius/radius_das.h | 1 +
72 src/radius/radius_server.c | 61 +-
73 src/rsn_supp/wpa.c | 3 +
74 src/tls/Makefile | 11 +
75 src/utils/eloop.c | 20 +-
76 src/utils/eloop.h | 8 +
77 src/utils/uloop.c | 64 +
78 src/utils/wpa_debug.c | 49 +-
79 src/utils/wpa_debug.h | 73 +-
developer05f3b2b2024-08-19 19:17:34 +080080 tests/Makefile | 76 +-
81 tests/hwsim/example-hostapd.config | 8 +-
82 tests/hwsim/example-wpa_supplicant.config | 9 +-
83 tests/hwsim/test_ap_eap.py | 114 +-
developer66e89bc2024-04-23 14:50:01 +080084 tests/hwsim/test_ap_ft.py | 4 +-
85 tests/hwsim/test_authsrv.py | 9 +-
86 tests/hwsim/test_dpp.py | 19 +-
87 tests/hwsim/test_erp.py | 16 +-
developer05f3b2b2024-08-19 19:17:34 +080088 tests/hwsim/test_fils.py | 4 +
developer66e89bc2024-04-23 14:50:01 +080089 tests/hwsim/test_pmksa_cache.py | 4 +-
90 tests/hwsim/test_sae.py | 7 +
91 tests/hwsim/test_suite_b.py | 3 +
92 tests/hwsim/test_wpas_ctrl.py | 2 +-
93 tests/hwsim/utils.py | 8 +-
94 tests/test-crypto_module.c | 16 +
95 tests/test-https.c | 12 +-
96 tests/test-https_server.c | 12 +-
developer05f3b2b2024-08-19 19:17:34 +080097 wpa_supplicant/Makefile | 143 +-
98 wpa_supplicant/ap.c | 28 +-
developer66e89bc2024-04-23 14:50:01 +080099 wpa_supplicant/config.c | 95 +
100 wpa_supplicant/config_file.c | 8 +-
developer05f3b2b2024-08-19 19:17:34 +0800101 wpa_supplicant/config_ssid.h | 5 +
developer66e89bc2024-04-23 14:50:01 +0800102 wpa_supplicant/ctrl_iface.c | 12 +-
103 wpa_supplicant/defconfig | 6 +-
104 wpa_supplicant/eapol_test.c | 11 +
developer05f3b2b2024-08-19 19:17:34 +0800105 wpa_supplicant/events.c | 7 +-
developer66e89bc2024-04-23 14:50:01 +0800106 wpa_supplicant/main.c | 14 +-
107 wpa_supplicant/mesh.c | 3 +
108 wpa_supplicant/wpa_cli.c | 9 +
109 wpa_supplicant/wpa_priv.c | 8 +-
developer05f3b2b2024-08-19 19:17:34 +0800110 wpa_supplicant/wpa_supplicant.c | 76 +-
developer66e89bc2024-04-23 14:50:01 +0800111 wpa_supplicant/wpa_supplicant_i.h | 6 +
112 wpa_supplicant/wps_supplicant.c | 3 +
113 wpa_supplicant/wps_supplicant.h | 3 +-
developer05f3b2b2024-08-19 19:17:34 +0800114 103 files changed, 9984 insertions(+), 401 deletions(-)
115 create mode 100644 src/ap/apup.c
116 create mode 100644 src/ap/apup.h
developer66e89bc2024-04-23 14:50:01 +0800117 create mode 100644 src/crypto/crypto_mbedtls.c
118 create mode 100644 src/crypto/tls_mbedtls.c
119 create mode 100644 src/utils/uloop.c
120 create mode 100644 tests/test-crypto_module.c
121
122diff --git a/hostapd/Makefile b/hostapd/Makefile
developer05f3b2b2024-08-19 19:17:34 +0800123index 78171025e..8dc6e6216 100644
developer66e89bc2024-04-23 14:50:01 +0800124--- a/hostapd/Makefile
125+++ b/hostapd/Makefile
126@@ -1,6 +1,7 @@
127 ALL=hostapd hostapd_cli
128 CONFIG_FILE = .config
129
130+-include $(if $(MULTICALL), ../wpa_supplicant/.config)
131 include ../src/build.rules
132
133 ifdef LIBS
134@@ -62,6 +63,10 @@ endif
135 OBJS += main.o
136 OBJS += config_file.o
137
138+ifdef CONFIG_RADIUS_SERVER
139+OBJS += radius.o
140+endif
141+
142 OBJS += ../src/ap/hostapd.o
143 OBJS += ../src/ap/wpa_auth_glue.o
144 OBJS += ../src/ap/drv_callbacks.o
developer05f3b2b2024-08-19 19:17:34 +0800145@@ -174,6 +179,24 @@ OBJS += ../src/common/hw_features_common.o
developer66e89bc2024-04-23 14:50:01 +0800146
147 OBJS += ../src/eapol_auth/eapol_auth_sm.o
148
149+ifdef CONFIG_UBUS
150+CFLAGS += -DUBUS_SUPPORT
151+OBJS += ../src/ap/ubus.o
152+LIBS += -lubus
153+NEED_ULOOP:=y
154+endif
155+
156+ifdef CONFIG_UCODE
157+CFLAGS += -DUCODE_SUPPORT
158+OBJS += ../src/utils/ucode.o
159+OBJS += ../src/ap/ucode.o
160+NEED_ULOOP:=y
161+endif
162+
163+ifdef NEED_ULOOP
164+OBJS += ../src/utils/uloop.o
165+LIBS += -lubox
166+endif
167
168 ifdef CONFIG_CODE_COVERAGE
169 CFLAGS += -O0 -fprofile-arcs -ftest-coverage -U_FORTIFY_SOURCE
developer05f3b2b2024-08-19 19:17:34 +0800170@@ -208,7 +231,8 @@ endif
developer66e89bc2024-04-23 14:50:01 +0800171
172 ifdef CONFIG_NO_VLAN
173 CFLAGS += -DCONFIG_NO_VLAN
174-else
175+endif
176+ifneq ($(findstring CONFIG_NO_VLAN,$(CFLAGS)), CONFIG_NO_VLAN)
177 OBJS += ../src/ap/vlan_init.o
178 OBJS += ../src/ap/vlan_ifconfig.o
179 OBJS += ../src/ap/vlan.o
developer05f3b2b2024-08-19 19:17:34 +0800180@@ -228,6 +252,9 @@ endif
developer66e89bc2024-04-23 14:50:01 +0800181 ifdef CONFIG_NO_CTRL_IFACE
182 CFLAGS += -DCONFIG_NO_CTRL_IFACE
183 else
184+ifdef CONFIG_CTRL_IFACE_MIB
185+CFLAGS += -DCONFIG_CTRL_IFACE_MIB
186+endif
187 ifeq ($(CONFIG_CTRL_IFACE), udp)
188 CFLAGS += -DCONFIG_CTRL_IFACE_UDP
189 else
developer05f3b2b2024-08-19 19:17:34 +0800190@@ -367,10 +394,14 @@ CFLAGS += -DCONFIG_MBO
developer66e89bc2024-04-23 14:50:01 +0800191 OBJS += ../src/ap/mbo_ap.o
192 endif
193
194+ifndef MULTICALL
195+CFLAGS += -DNO_SUPPLICANT
196+endif
197+
198 include ../src/drivers/drivers.mak
199-OBJS += $(DRV_AP_OBJS)
200-CFLAGS += $(DRV_AP_CFLAGS)
201-LDFLAGS += $(DRV_AP_LDFLAGS)
202+OBJS += $(sort $(DRV_AP_OBJS) $(if $(MULTICALL),$(DRV_WPA_OBJS)))
203+CFLAGS += $(DRV_AP_CFLAGS) $(if $(MULTICALL),$(DRV_WPA_CFLAGS))
204+LDFLAGS += $(DRV_AP_LDFLAGS) $(if $(MULTICALL),$(DRV_WPA_LDFLAGS))
205 LIBS += $(DRV_AP_LIBS)
206
207 ifdef CONFIG_L2_PACKET
developer05f3b2b2024-08-19 19:17:34 +0800208@@ -716,6 +747,7 @@ CFLAGS += -DCONFIG_TLSV12
developer66e89bc2024-04-23 14:50:01 +0800209 endif
210
211 ifeq ($(CONFIG_TLS), wolfssl)
212+CFLAGS += -DCONFIG_TLS_WOLFSSL
213 CONFIG_CRYPTO=wolfssl
214 ifdef TLS_FUNCS
215 OBJS += ../src/crypto/tls_wolfssl.o
developer05f3b2b2024-08-19 19:17:34 +0800216@@ -736,6 +768,7 @@ endif
developer66e89bc2024-04-23 14:50:01 +0800217 endif
218
219 ifeq ($(CONFIG_TLS), openssl)
220+CFLAGS += -DCONFIG_TLS_OPENSSL
221 CFLAGS += -DCRYPTO_RSA_OAEP_SHA256
222 CONFIG_CRYPTO=openssl
223 ifdef TLS_FUNCS
developer05f3b2b2024-08-19 19:17:34 +0800224@@ -765,7 +798,39 @@ endif
developer66e89bc2024-04-23 14:50:01 +0800225 CFLAGS += -DTLS_DEFAULT_CIPHERS=\"$(CONFIG_TLS_DEFAULT_CIPHERS)\"
226 endif
227
228+ifeq ($(CONFIG_TLS), mbedtls)
229+CFLAGS += -DCONFIG_TLS_MBEDTLS
230+ifndef CONFIG_CRYPTO
231+CONFIG_CRYPTO=mbedtls
232+endif
233+ifdef TLS_FUNCS
234+OBJS += ../src/crypto/tls_mbedtls.o
235+LIBS += -lmbedtls
236+ifndef CONFIG_DPP
237+LIBS += -lmbedx509
238+endif
239+endif
240+OBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o
241+HOBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o
242+SOBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o
243+ifeq ($(CONFIG_CRYPTO), mbedtls)
244+ifdef CONFIG_DPP
245+LIBS += -lmbedx509
246+LIBS_h += -lmbedx509
247+LIBS_n += -lmbedx509
248+LIBS_s += -lmbedx509
249+endif
250+LIBS += -lmbedcrypto
251+LIBS_h += -lmbedcrypto
252+LIBS_n += -lmbedcrypto
253+LIBS_s += -lmbedcrypto
254+# XXX: create a config option?
255+CFLAGS += -DCRYPTO_RSA_OAEP_SHA256
256+endif
257+endif
258+
259 ifeq ($(CONFIG_TLS), gnutls)
260+CFLAGS += -DCONFIG_TLS_GNUTLS
261 ifndef CONFIG_CRYPTO
262 # default to libgcrypt
263 CONFIG_CRYPTO=gnutls
developer05f3b2b2024-08-19 19:17:34 +0800264@@ -796,6 +861,7 @@ endif
developer66e89bc2024-04-23 14:50:01 +0800265 endif
266
267 ifeq ($(CONFIG_TLS), internal)
268+CFLAGS += -DCONFIG_TLS_INTERNAL
269 ifndef CONFIG_CRYPTO
270 CONFIG_CRYPTO=internal
271 endif
developer05f3b2b2024-08-19 19:17:34 +0800272@@ -874,6 +940,7 @@ endif
developer66e89bc2024-04-23 14:50:01 +0800273 endif
274
275 ifeq ($(CONFIG_TLS), linux)
276+CFLAGS += -DCONFIG_TLS_INTERNAL
277 OBJS += ../src/crypto/crypto_linux.o
278 ifdef TLS_FUNCS
279 OBJS += ../src/crypto/crypto_internal-rsa.o
developer05f3b2b2024-08-19 19:17:34 +0800280@@ -944,9 +1011,11 @@ endif
developer66e89bc2024-04-23 14:50:01 +0800281
282 ifneq ($(CONFIG_TLS), openssl)
283 ifneq ($(CONFIG_TLS), wolfssl)
284+ifneq ($(CONFIG_TLS), mbedtls)
285 AESOBJS += ../src/crypto/aes-wrap.o
286 endif
287 endif
288+endif
289 ifdef NEED_AES_EAX
290 AESOBJS += ../src/crypto/aes-eax.o
291 NEED_AES_CTR=y
developer05f3b2b2024-08-19 19:17:34 +0800292@@ -956,38 +1025,48 @@ AESOBJS += ../src/crypto/aes-siv.o
developer66e89bc2024-04-23 14:50:01 +0800293 NEED_AES_CTR=y
294 endif
295 ifdef NEED_AES_CTR
296+ifneq ($(CONFIG_TLS), mbedtls)
297 AESOBJS += ../src/crypto/aes-ctr.o
298 endif
299+endif
300 ifdef NEED_AES_ENCBLOCK
301+ifneq ($(CONFIG_TLS), mbedtls)
302 AESOBJS += ../src/crypto/aes-encblock.o
303 endif
304+endif
305 ifneq ($(CONFIG_TLS), openssl)
306 ifneq ($(CONFIG_TLS), linux)
307 ifneq ($(CONFIG_TLS), wolfssl)
308+ifneq ($(CONFIG_TLS), mbedtls)
309 AESOBJS += ../src/crypto/aes-omac1.o
310 endif
311 endif
312 endif
313+endif
314 ifdef NEED_AES_UNWRAP
315 ifneq ($(CONFIG_TLS), openssl)
316 ifneq ($(CONFIG_TLS), linux)
317 ifneq ($(CONFIG_TLS), wolfssl)
318+ifneq ($(CONFIG_TLS), mbedtls)
319 NEED_AES_DEC=y
320 AESOBJS += ../src/crypto/aes-unwrap.o
321 endif
322 endif
323 endif
324 endif
325+endif
326 ifdef NEED_AES_CBC
327 NEED_AES_DEC=y
328 ifneq ($(CONFIG_TLS), openssl)
329 ifneq ($(CONFIG_TLS), linux)
330 ifneq ($(CONFIG_TLS), wolfssl)
331+ifneq ($(CONFIG_TLS), mbedtls)
332 AESOBJS += ../src/crypto/aes-cbc.o
333 endif
334 endif
335 endif
336 endif
337+endif
338 ifdef NEED_AES_DEC
339 ifdef CONFIG_INTERNAL_AES
340 AESOBJS += ../src/crypto/aes-internal-dec.o
developer05f3b2b2024-08-19 19:17:34 +0800341@@ -1002,12 +1081,16 @@ ifneq ($(CONFIG_TLS), openssl)
developer66e89bc2024-04-23 14:50:01 +0800342 ifneq ($(CONFIG_TLS), linux)
343 ifneq ($(CONFIG_TLS), gnutls)
344 ifneq ($(CONFIG_TLS), wolfssl)
345+ifneq ($(CONFIG_TLS), mbedtls)
346 SHA1OBJS += ../src/crypto/sha1.o
347 endif
348 endif
349 endif
350 endif
351+endif
352+ifneq ($(CONFIG_TLS), mbedtls)
353 SHA1OBJS += ../src/crypto/sha1-prf.o
354+endif
355 ifdef CONFIG_INTERNAL_SHA1
356 SHA1OBJS += ../src/crypto/sha1-internal.o
357 ifdef NEED_FIPS186_2_PRF
developer05f3b2b2024-08-19 19:17:34 +0800358@@ -1016,16 +1099,22 @@ endif
developer66e89bc2024-04-23 14:50:01 +0800359 endif
360 ifneq ($(CONFIG_TLS), openssl)
361 ifneq ($(CONFIG_TLS), wolfssl)
362+ifneq ($(CONFIG_TLS), mbedtls)
363 SHA1OBJS += ../src/crypto/sha1-pbkdf2.o
364 endif
365 endif
366+endif
367 ifdef NEED_T_PRF
368+ifneq ($(CONFIG_TLS), mbedtls)
369 SHA1OBJS += ../src/crypto/sha1-tprf.o
370 endif
371+endif
372 ifdef NEED_TLS_PRF
373+ifneq ($(CONFIG_TLS), mbedtls)
374 SHA1OBJS += ../src/crypto/sha1-tlsprf.o
375 endif
376 endif
377+endif
378
379 ifdef NEED_SHA1
380 OBJS += $(SHA1OBJS)
developer05f3b2b2024-08-19 19:17:34 +0800381@@ -1035,11 +1124,13 @@ ifneq ($(CONFIG_TLS), openssl)
developer66e89bc2024-04-23 14:50:01 +0800382 ifneq ($(CONFIG_TLS), linux)
383 ifneq ($(CONFIG_TLS), gnutls)
384 ifneq ($(CONFIG_TLS), wolfssl)
385+ifneq ($(CONFIG_TLS), mbedtls)
386 OBJS += ../src/crypto/md5.o
387 endif
388 endif
389 endif
390 endif
391+endif
392
393 ifdef NEED_MD5
394 ifdef CONFIG_INTERNAL_MD5
developer05f3b2b2024-08-19 19:17:34 +0800395@@ -1078,56 +1169,81 @@ ifneq ($(CONFIG_TLS), openssl)
developer66e89bc2024-04-23 14:50:01 +0800396 ifneq ($(CONFIG_TLS), linux)
397 ifneq ($(CONFIG_TLS), gnutls)
398 ifneq ($(CONFIG_TLS), wolfssl)
399+ifneq ($(CONFIG_TLS), mbedtls)
400 OBJS += ../src/crypto/sha256.o
401 endif
402 endif
403 endif
404 endif
405+endif
406+ifneq ($(CONFIG_TLS), mbedtls)
407 OBJS += ../src/crypto/sha256-prf.o
408+endif
409 ifdef CONFIG_INTERNAL_SHA256
410 OBJS += ../src/crypto/sha256-internal.o
411 endif
412 ifdef NEED_TLS_PRF_SHA256
413+ifneq ($(CONFIG_TLS), mbedtls)
414 OBJS += ../src/crypto/sha256-tlsprf.o
415 endif
416+endif
417 ifdef NEED_TLS_PRF_SHA384
418+ifneq ($(CONFIG_TLS), mbedtls)
419 OBJS += ../src/crypto/sha384-tlsprf.o
420 endif
421+endif
422 ifdef NEED_HMAC_SHA256_KDF
423+CFLAGS += -DCONFIG_HMAC_SHA256_KDF
424+ifneq ($(CONFIG_TLS), mbedtls)
425 OBJS += ../src/crypto/sha256-kdf.o
426 endif
427+endif
428 ifdef NEED_HMAC_SHA384_KDF
429+CFLAGS += -DCONFIG_HMAC_SHA384_KDF
430+ifneq ($(CONFIG_TLS), mbedtls)
431 OBJS += ../src/crypto/sha384-kdf.o
432 endif
433+endif
434 ifdef NEED_HMAC_SHA512_KDF
435+CFLAGS += -DCONFIG_HMAC_SHA512_KDF
436+ifneq ($(CONFIG_TLS), mbedtls)
437 OBJS += ../src/crypto/sha512-kdf.o
438 endif
439+endif
440 ifdef NEED_SHA384
441 CFLAGS += -DCONFIG_SHA384
442 ifneq ($(CONFIG_TLS), openssl)
443 ifneq ($(CONFIG_TLS), linux)
444 ifneq ($(CONFIG_TLS), gnutls)
445 ifneq ($(CONFIG_TLS), wolfssl)
446+ifneq ($(CONFIG_TLS), mbedtls)
447 OBJS += ../src/crypto/sha384.o
448 endif
449 endif
450 endif
451 endif
452+endif
453+ifneq ($(CONFIG_TLS), mbedtls)
454 OBJS += ../src/crypto/sha384-prf.o
455 endif
456+endif
457 ifdef NEED_SHA512
458 CFLAGS += -DCONFIG_SHA512
459 ifneq ($(CONFIG_TLS), openssl)
460 ifneq ($(CONFIG_TLS), linux)
461 ifneq ($(CONFIG_TLS), gnutls)
462 ifneq ($(CONFIG_TLS), wolfssl)
463+ifneq ($(CONFIG_TLS), mbedtls)
464 OBJS += ../src/crypto/sha512.o
465 endif
466 endif
467 endif
468 endif
469+endif
470+ifneq ($(CONFIG_TLS), mbedtls)
471 OBJS += ../src/crypto/sha512-prf.o
472 endif
473+endif
474
475 ifdef CONFIG_INTERNAL_SHA384
476 CFLAGS += -DCONFIG_INTERNAL_SHA384
developer05f3b2b2024-08-19 19:17:34 +0800477@@ -1172,11 +1288,13 @@ HOBJS += $(SHA1OBJS)
developer66e89bc2024-04-23 14:50:01 +0800478 ifneq ($(CONFIG_TLS), openssl)
479 ifneq ($(CONFIG_TLS), linux)
480 ifneq ($(CONFIG_TLS), wolfssl)
481+ifneq ($(CONFIG_TLS), mbedtls)
482 HOBJS += ../src/crypto/md5.o
483 endif
484 endif
485 endif
486 endif
487+endif
488
489 ifdef CONFIG_RADIUS_SERVER
490 CFLAGS += -DRADIUS_SERVER
developer05f3b2b2024-08-19 19:17:34 +0800491@@ -1306,6 +1424,11 @@ ifdef CONFIG_NO_TKIP
492 CFLAGS += -DCONFIG_NO_TKIP
493 endif
494
495+ifdef CONFIG_APUP
496+CFLAGS += -DCONFIG_APUP
497+OBJS += ../src/ap/apup.o
498+endif
499+
500 $(DESTDIR)$(BINDIR)/%: %
501 install -D $(<) $(@)
502
503@@ -1314,8 +1437,14 @@ install: $(addprefix $(DESTDIR)$(BINDIR)/,$(ALL))
developer66e89bc2024-04-23 14:50:01 +0800504 _OBJS_VAR := OBJS
505 include ../src/objs.mk
506
507+hostapd_multi.a: $(BCHECK) $(OBJS)
508+ $(Q)$(CC) -c -o hostapd_multi.o -Dmain=hostapd_main $(CFLAGS) main.c
509+ @$(E) " CC " $<
510+ @rm -f $@
511+ @$(AR) cr $@ hostapd_multi.o $(OBJS)
512+
513 hostapd: $(OBJS)
514- $(Q)$(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS)
515+ +$(Q)$(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS)
516 @$(E) " LD " $@
517
518 ifdef CONFIG_WPA_TRACE
developer05f3b2b2024-08-19 19:17:34 +0800519@@ -1326,7 +1455,7 @@ _OBJS_VAR := OBJS_c
developer66e89bc2024-04-23 14:50:01 +0800520 include ../src/objs.mk
521
522 hostapd_cli: $(OBJS_c)
523- $(Q)$(CC) $(LDFLAGS) -o hostapd_cli $(OBJS_c) $(LIBS_c)
524+ +$(Q)$(CC) $(LDFLAGS) -o hostapd_cli $(OBJS_c) $(LIBS_c)
525 @$(E) " LD " $@
526
527 NOBJS = nt_password_hash.o ../src/crypto/ms_funcs.o $(SHA1OBJS)
developer05f3b2b2024-08-19 19:17:34 +0800528@@ -1350,7 +1479,9 @@ NOBJS += ../src/utils/trace.o
developer66e89bc2024-04-23 14:50:01 +0800529 endif
530
531 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
532+ifneq ($(CONFIG_TLS), mbedtls)
533 HOBJS += ../src/crypto/aes-encblock.o
534+endif
535 ifdef CONFIG_INTERNAL_AES
536 HOBJS += ../src/crypto/aes-internal.o
537 HOBJS += ../src/crypto/aes-internal-enc.o
developer05f3b2b2024-08-19 19:17:34 +0800538@@ -1373,13 +1504,17 @@ SOBJS += ../src/common/sae.o
developer66e89bc2024-04-23 14:50:01 +0800539 SOBJS += ../src/common/sae_pk.o
540 SOBJS += ../src/common/dragonfly.o
541 SOBJS += $(AESOBJS)
542+ifneq ($(CONFIG_TLS), mbedtls)
543 SOBJS += ../src/crypto/sha256-prf.o
544 SOBJS += ../src/crypto/sha384-prf.o
545 SOBJS += ../src/crypto/sha512-prf.o
546+endif
547 SOBJS += ../src/crypto/dh_groups.o
548+ifneq ($(CONFIG_TLS), mbedtls)
549 SOBJS += ../src/crypto/sha256-kdf.o
550 SOBJS += ../src/crypto/sha384-kdf.o
551 SOBJS += ../src/crypto/sha512-kdf.o
552+endif
553
554 _OBJS_VAR := NOBJS
555 include ../src/objs.mk
developer05f3b2b2024-08-19 19:17:34 +0800556@@ -1388,6 +1523,12 @@ include ../src/objs.mk
developer66e89bc2024-04-23 14:50:01 +0800557 _OBJS_VAR := SOBJS
558 include ../src/objs.mk
559
560+dump_cflags:
561+ @printf "%s " "$(CFLAGS)"
562+
563+dump_ldflags:
564+ @printf "%s " "$(LDFLAGS) $(LIBS) $(EXTRALIBS)"
565+
566 nt_password_hash: $(NOBJS)
567 $(Q)$(CC) $(LDFLAGS) -o nt_password_hash $(NOBJS) $(LIBS_n)
568 @$(E) " LD " $@
569diff --git a/hostapd/config_file.c b/hostapd/config_file.c
developer05f3b2b2024-08-19 19:17:34 +0800570index a86621ed9..f3968ec95 100644
developer66e89bc2024-04-23 14:50:01 +0800571--- a/hostapd/config_file.c
572+++ b/hostapd/config_file.c
573@@ -1229,6 +1229,8 @@ static int hostapd_config_vht_capab(struct hostapd_config *conf,
574 conf->vht_capab |= VHT_CAP_RX_ANTENNA_PATTERN;
575 if (os_strstr(capab, "[TX-ANTENNA-PATTERN]"))
576 conf->vht_capab |= VHT_CAP_TX_ANTENNA_PATTERN;
577+ if (os_strstr(capab, "[EXT-NSS-BW-SUPP]"))
578+ conf->vht_capab |= VHT_CAP_EXTENDED_NSS_BW_SUPPORT;
579 return 0;
580 }
581 #endif /* CONFIG_IEEE80211AC */
developer05f3b2b2024-08-19 19:17:34 +0800582@@ -2654,8 +2656,12 @@ static int hostapd_config_fill(struct hostapd_config *conf,
developer66e89bc2024-04-23 14:50:01 +0800583 sizeof(conf->bss[0]->iface));
584 } else if (os_strcmp(buf, "bridge") == 0) {
585 os_strlcpy(bss->bridge, pos, sizeof(bss->bridge));
586+ if (!bss->wds_bridge[0])
587+ os_strlcpy(bss->wds_bridge, pos, sizeof(bss->wds_bridge));
588 } else if (os_strcmp(buf, "bridge_hairpin") == 0) {
589 bss->bridge_hairpin = atoi(pos);
590+ } else if (os_strcmp(buf, "snoop_iface") == 0) {
591+ os_strlcpy(bss->snoop_iface, pos, sizeof(bss->snoop_iface));
592 } else if (os_strcmp(buf, "vlan_bridge") == 0) {
593 os_strlcpy(bss->vlan_bridge, pos, sizeof(bss->vlan_bridge));
594 } else if (os_strcmp(buf, "wds_bridge") == 0) {
developer05f3b2b2024-08-19 19:17:34 +0800595@@ -3043,6 +3049,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
developer66e89bc2024-04-23 14:50:01 +0800596 } else if (os_strcmp(buf, "iapp_interface") == 0) {
597 wpa_printf(MSG_INFO, "DEPRECATED: iapp_interface not used");
598 #endif /* CONFIG_IAPP */
599+ } else if (os_strcmp(buf, "dynamic_own_ip_addr") == 0) {
600+ bss->dynamic_own_ip_addr = atoi(pos);
601 } else if (os_strcmp(buf, "own_ip_addr") == 0) {
602 if (hostapd_parse_ip_addr(pos, &bss->own_ip_addr)) {
603 wpa_printf(MSG_ERROR,
developer05f3b2b2024-08-19 19:17:34 +0800604@@ -3270,6 +3278,14 @@ static int hostapd_config_fill(struct hostapd_config *conf,
developer66e89bc2024-04-23 14:50:01 +0800605 line, bss->max_num_sta, MAX_STA_COUNT);
606 return 1;
607 }
608+ } else if (os_strcmp(buf, "iface_max_num_sta") == 0) {
609+ conf->max_num_sta = atoi(pos);
610+ if (conf->max_num_sta < 0 ||
611+ conf->max_num_sta > MAX_STA_COUNT) {
612+ wpa_printf(MSG_ERROR, "Line %d: Invalid max_num_sta=%d; allowed range 0..%d",
613+ line, conf->max_num_sta, MAX_STA_COUNT);
614+ return 1;
615+ }
616 } else if (os_strcmp(buf, "wpa") == 0) {
617 bss->wpa = atoi(pos);
618 } else if (os_strcmp(buf, "extended_key_id") == 0) {
developer05f3b2b2024-08-19 19:17:34 +0800619@@ -3459,6 +3475,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
developer66e89bc2024-04-23 14:50:01 +0800620 wpa_printf(MSG_INFO,
621 "Line %d: Obsolete peerkey parameter ignored", line);
622 #ifdef CONFIG_IEEE80211R_AP
623+ } else if (os_strcmp(buf, "ft_iface") == 0) {
624+ os_strlcpy(bss->ft_iface, pos, sizeof(bss->ft_iface));
625 } else if (os_strcmp(buf, "mobility_domain") == 0) {
626 if (os_strlen(pos) != 2 * MOBILITY_DOMAIN_ID_LEN ||
627 hexstr2bin(pos, bss->mobility_domain,
developer05f3b2b2024-08-19 19:17:34 +0800628@@ -3828,6 +3846,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
developer66e89bc2024-04-23 14:50:01 +0800629 #ifndef CONFIG_NO_VLAN
630 } else if (os_strcmp(buf, "dynamic_vlan") == 0) {
631 bss->ssid.dynamic_vlan = atoi(pos);
632+ } else if (os_strcmp(buf, "vlan_no_bridge") == 0) {
633+ bss->ssid.vlan_no_bridge = atoi(pos);
634 } else if (os_strcmp(buf, "per_sta_vif") == 0) {
635 bss->ssid.per_sta_vif = atoi(pos);
636 } else if (os_strcmp(buf, "vlan_file") == 0) {
developer05f3b2b2024-08-19 19:17:34 +0800637@@ -3929,6 +3949,10 @@ static int hostapd_config_fill(struct hostapd_config *conf,
developer66e89bc2024-04-23 14:50:01 +0800638 if (bss->ocv && !bss->ieee80211w)
639 bss->ieee80211w = 1;
640 #endif /* CONFIG_OCV */
641+ } else if (os_strcmp(buf, "noscan") == 0) {
642+ conf->noscan = atoi(pos);
643+ } else if (os_strcmp(buf, "ht_coex") == 0) {
644+ conf->no_ht_coex = !atoi(pos);
645 } else if (os_strcmp(buf, "ieee80211n") == 0) {
646 conf->ieee80211n = atoi(pos);
647 } else if (os_strcmp(buf, "ht_capab") == 0) {
developer05f3b2b2024-08-19 19:17:34 +0800648@@ -3979,6 +4003,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
developer66e89bc2024-04-23 14:50:01 +0800649 } else if (os_strcmp(buf, "he_bss_color") == 0) {
650 conf->he_op.he_bss_color = atoi(pos) & 0x3f;
651 conf->he_op.he_bss_color_disabled = 0;
652+ if (atoi(pos) > 63)
653+ conf->he_op.he_bss_color = os_random() % 63 + 1;
654 } else if (os_strcmp(buf, "he_bss_color_partial") == 0) {
655 conf->he_op.he_bss_color_partial = atoi(pos);
656 } else if (os_strcmp(buf, "he_default_pe_duration") == 0) {
developer05f3b2b2024-08-19 19:17:34 +0800657@@ -5435,6 +5461,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
658 bss->mld_indicate_disabled = atoi(pos);
659 #endif /* CONFIG_TESTING_OPTIONS */
660 #endif /* CONFIG_IEEE80211BE */
661+#ifdef CONFIG_APUP
662+ } else if (os_strcmp(buf, "apup") == 0) {
663+ bss->apup = !!atoi(pos);
664+ if (bss->apup)
665+ bss->wds_sta = 1;
666+ } else if (os_strcmp(buf, "apup_peer_ifname_prefix") == 0) {
667+ os_strlcpy(bss->apup_peer_ifname_prefix,
668+ pos, sizeof(bss->apup_peer_ifname_prefix));
669+#endif // def CONFIG_APUP
670 } else {
671 wpa_printf(MSG_ERROR,
672 "Line %d: unknown configuration item '%s'",
673@@ -5460,7 +5495,12 @@ struct hostapd_config * hostapd_config_read(const char *fname)
developer66e89bc2024-04-23 14:50:01 +0800674 int errors = 0;
675 size_t i;
676
677- f = fopen(fname, "r");
678+ if (!strncmp(fname, "data:", 5)) {
679+ f = fmemopen((void *)(fname + 5), strlen(fname + 5), "r");
680+ fname = "<inline>";
681+ } else {
682+ f = fopen(fname, "r");
683+ }
684 if (f == NULL) {
685 wpa_printf(MSG_ERROR, "Could not open configuration file '%s' "
686 "for reading.", fname);
687diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
developer05f3b2b2024-08-19 19:17:34 +0800688index a584d370e..1d5922fab 100644
developer66e89bc2024-04-23 14:50:01 +0800689--- a/hostapd/ctrl_iface.c
690+++ b/hostapd/ctrl_iface.c
developer05f3b2b2024-08-19 19:17:34 +0800691@@ -4005,6 +4005,7 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
developer66e89bc2024-04-23 14:50:01 +0800692 reply_size);
693 } else if (os_strcmp(buf, "STATUS-DRIVER") == 0) {
694 reply_len = hostapd_drv_status(hapd, reply, reply_size);
695+#ifdef CONFIG_CTRL_IFACE_MIB
696 } else if (os_strcmp(buf, "MIB") == 0) {
697 reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
698 if (reply_len >= 0) {
developer05f3b2b2024-08-19 19:17:34 +0800699@@ -4046,6 +4047,7 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
developer66e89bc2024-04-23 14:50:01 +0800700 } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
701 reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply,
702 reply_size);
703+#endif
704 } else if (os_strcmp(buf, "ATTACH") == 0) {
705 if (hostapd_ctrl_iface_attach(hapd, from, fromlen, NULL))
706 reply_len = -1;
developer05f3b2b2024-08-19 19:17:34 +0800707@@ -5994,6 +5996,7 @@ try_again:
developer66e89bc2024-04-23 14:50:01 +0800708 return -1;
709 }
710
711+ interface->ctrl_iface_recv = hostapd_ctrl_iface_receive_process;
712 wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
713
714 return 0;
developer05f3b2b2024-08-19 19:17:34 +0800715@@ -6095,6 +6098,7 @@ fail:
developer66e89bc2024-04-23 14:50:01 +0800716 os_free(fname);
717
718 interface->global_ctrl_sock = s;
719+ interface->ctrl_iface_recv = hostapd_ctrl_iface_receive_process;
720 eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
721 interface, NULL);
722
723diff --git a/hostapd/defconfig b/hostapd/defconfig
724index 66bf894eb..f716553bb 100644
725--- a/hostapd/defconfig
726+++ b/hostapd/defconfig
727@@ -6,9 +6,21 @@
728 # just setting VARIABLE=n is not disabling that variable.
729 #
730 # This file is included in Makefile, so variables like CFLAGS and LIBS can also
731-# be modified from here. In most cass, these lines should use += in order not
732+# be modified from here. In most cases, these lines should use += in order not
733 # to override previous values of the variables.
734
735+
736+# Uncomment following two lines and fix the paths if you have installed TLS
737+# libraries in a non-default location
738+#CFLAGS += -I/usr/local/openssl/include
739+#LIBS += -L/usr/local/openssl/lib
740+
741+# Some Red Hat versions seem to include kerberos header files from OpenSSL, but
742+# the kerberos files are not in the default include path. Following line can be
743+# used to fix build issues on such systems (krb5.h not found).
744+#CFLAGS += -I/usr/include/kerberos
745+
746+
747 # Driver interface for Host AP driver
748 CONFIG_DRIVER_HOSTAP=y
749
750@@ -281,6 +293,7 @@ CONFIG_IPV6=y
751 # openssl = OpenSSL (default)
752 # gnutls = GnuTLS
753 # internal = Internal TLSv1 implementation (experimental)
754+# mbedtls = mbed TLS
755 # linux = Linux kernel AF_ALG and internal TLSv1 implementation (experimental)
756 # none = Empty template
757 #CONFIG_TLS=openssl
758diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
developer05f3b2b2024-08-19 19:17:34 +0800759index d69525502..ebf8addc1 100644
developer66e89bc2024-04-23 14:50:01 +0800760--- a/hostapd/hostapd_cli.c
761+++ b/hostapd/hostapd_cli.c
developer05f3b2b2024-08-19 19:17:34 +0800762@@ -410,7 +410,6 @@ static int hostapd_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
developer66e89bc2024-04-23 14:50:01 +0800763 }
764
765
766-#ifdef CONFIG_TAXONOMY
767 static int hostapd_cli_cmd_signature(struct wpa_ctrl *ctrl, int argc,
768 char *argv[])
769 {
developer05f3b2b2024-08-19 19:17:34 +0800770@@ -423,7 +422,6 @@ static int hostapd_cli_cmd_signature(struct wpa_ctrl *ctrl, int argc,
developer66e89bc2024-04-23 14:50:01 +0800771 os_snprintf(buf, sizeof(buf), "SIGNATURE %s", argv[0]);
772 return wpa_ctrl_command(ctrl, buf);
773 }
774-#endif /* CONFIG_TAXONOMY */
775
776
777 static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
developer05f3b2b2024-08-19 19:17:34 +0800778@@ -440,7 +438,6 @@ static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
developer66e89bc2024-04-23 14:50:01 +0800779 }
780
781
782-#ifdef CONFIG_WPS
783 static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,
784 char *argv[])
785 {
developer05f3b2b2024-08-19 19:17:34 +0800786@@ -666,7 +663,6 @@ static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
developer66e89bc2024-04-23 14:50:01 +0800787 ssid_hex, argv[1]);
788 return wpa_ctrl_command(ctrl, buf);
789 }
790-#endif /* CONFIG_WPS */
791
792
793 static int hostapd_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc,
developer05f3b2b2024-08-19 19:17:34 +0800794@@ -766,7 +762,7 @@ static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, const char *cmd,
developer66e89bc2024-04-23 14:50:01 +0800795 }
796
797 buf[len] = '\0';
798- if (memcmp(buf, "FAIL", 4) == 0)
799+ if (memcmp(buf, "FAIL", 4) == 0 || memcmp(buf, "UNKNOWN COMMAND", 15) == 0)
800 return -1;
801 if (print)
802 printf("%s", buf);
developer05f3b2b2024-08-19 19:17:34 +0800803@@ -1695,13 +1691,10 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
developer66e89bc2024-04-23 14:50:01 +0800804 { "disassociate", hostapd_cli_cmd_disassociate,
805 hostapd_complete_stations,
806 "<addr> = disassociate a station" },
807-#ifdef CONFIG_TAXONOMY
808 { "signature", hostapd_cli_cmd_signature, hostapd_complete_stations,
809 "<addr> = get taxonomy signature for a station" },
810-#endif /* CONFIG_TAXONOMY */
811 { "sa_query", hostapd_cli_cmd_sa_query, hostapd_complete_stations,
812 "<addr> = send SA Query to a station" },
813-#ifdef CONFIG_WPS
814 { "wps_pin", hostapd_cli_cmd_wps_pin, NULL,
815 "<uuid> <pin> [timeout] [addr] = add WPS Enrollee PIN" },
816 { "wps_check_pin", hostapd_cli_cmd_wps_check_pin, NULL,
developer05f3b2b2024-08-19 19:17:34 +0800817@@ -1726,7 +1719,6 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
developer66e89bc2024-04-23 14:50:01 +0800818 "<SSID> <auth> <encr> <key> = configure AP" },
819 { "wps_get_status", hostapd_cli_cmd_wps_get_status, NULL,
820 "= show current WPS status" },
821-#endif /* CONFIG_WPS */
822 { "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent, NULL,
823 "= send Disassociation Imminent notification" },
824 { "ess_disassoc", hostapd_cli_cmd_ess_disassoc, NULL,
825diff --git a/hostapd/main.c b/hostapd/main.c
developer05f3b2b2024-08-19 19:17:34 +0800826index aa1f69812..e790f18ce 100644
developer66e89bc2024-04-23 14:50:01 +0800827--- a/hostapd/main.c
828+++ b/hostapd/main.c
829@@ -31,7 +31,7 @@
830 #include "config_file.h"
831 #include "eap_register.h"
832 #include "ctrl_iface.h"
833-
834+#include "build_features.h"
835
836 struct hapd_global {
837 void **drv_priv;
838@@ -40,6 +40,7 @@ struct hapd_global {
839
840 static struct hapd_global global;
841
842+extern int radius_main(int argc, char **argv);
843
844 #ifndef CONFIG_NO_HOSTAPD_LOGGER
845 static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module,
developer05f3b2b2024-08-19 19:17:34 +0800846@@ -692,6 +693,11 @@ fail:
developer66e89bc2024-04-23 14:50:01 +0800847 return -1;
848 }
849
850+void hostapd_wpa_event(void *ctx, enum wpa_event_type event,
851+ union wpa_event_data *data);
852+
853+void hostapd_wpa_event_global(void *ctx, enum wpa_event_type event,
854+ union wpa_event_data *data);
855
856 #ifdef CONFIG_WPS
857 static int gen_uuid(const char *txt_addr)
developer05f3b2b2024-08-19 19:17:34 +0800858@@ -784,6 +790,11 @@ int main(int argc, char *argv[])
developer66e89bc2024-04-23 14:50:01 +0800859 if (os_program_init())
860 return -1;
861
862+#ifdef RADIUS_SERVER
863+ if (strstr(argv[0], "radius"))
864+ return radius_main(argc, argv);
865+#endif
866+
867 os_memset(&interfaces, 0, sizeof(interfaces));
868 interfaces.reload_config = hostapd_reload_config;
869 interfaces.config_read_cb = hostapd_config_read;
developer05f3b2b2024-08-19 19:17:34 +0800870@@ -813,8 +824,10 @@ int main(int argc, char *argv[])
developer66e89bc2024-04-23 14:50:01 +0800871 return -1;
872 #endif /* CONFIG_DPP */
873
874+ wpa_supplicant_event = hostapd_wpa_event;
875+ wpa_supplicant_event_global = hostapd_wpa_event_global;
876 for (;;) {
877- c = getopt(argc, argv, "b:Bde:f:hi:KP:sSTtu:vg:G:q");
878+ c = getopt(argc, argv, "b:Bde:f:hi:KP:sSTtu:g:G:qv::");
879 if (c < 0)
880 break;
881 switch (c) {
developer05f3b2b2024-08-19 19:17:34 +0800882@@ -851,6 +864,8 @@ int main(int argc, char *argv[])
developer66e89bc2024-04-23 14:50:01 +0800883 break;
884 #endif /* CONFIG_DEBUG_LINUX_TRACING */
885 case 'v':
886+ if (optarg)
887+ exit(!has_feature(optarg));
888 show_version();
889 exit(1);
890 case 'g':
developer05f3b2b2024-08-19 19:17:34 +0800891@@ -1020,6 +1035,7 @@ int main(int argc, char *argv[])
developer66e89bc2024-04-23 14:50:01 +0800892 }
893
894 hostapd_global_ctrl_iface_init(&interfaces);
895+ hostapd_ucode_init(&interfaces);
896
897 if (hostapd_global_run(&interfaces, daemonize, pid_file)) {
898 wpa_printf(MSG_ERROR, "Failed to start eloop");
developer05f3b2b2024-08-19 19:17:34 +0800899@@ -1029,6 +1045,7 @@ int main(int argc, char *argv[])
developer66e89bc2024-04-23 14:50:01 +0800900 ret = 0;
901
902 out:
903+ hostapd_ucode_free();
904 hostapd_global_ctrl_iface_deinit(&interfaces);
905 /* Deinitialize all interfaces */
906 for (i = 0; i < interfaces.count; i++) {
907diff --git a/src/ap/acs.c b/src/ap/acs.c
developer05f3b2b2024-08-19 19:17:34 +0800908index f5b36d327..25fec499a 100644
developer66e89bc2024-04-23 14:50:01 +0800909--- a/src/ap/acs.c
910+++ b/src/ap/acs.c
developer05f3b2b2024-08-19 19:17:34 +0800911@@ -471,17 +471,17 @@ static int acs_get_bw_center_chan(int freq, enum bw_type bw)
developer66e89bc2024-04-23 14:50:01 +0800912 static int acs_survey_is_sufficient(struct freq_survey *survey)
913 {
914 if (!(survey->filled & SURVEY_HAS_NF)) {
915+ survey->nf = -95;
916 wpa_printf(MSG_INFO,
917 "ACS: Survey for freq %d is missing noise floor",
918 survey->freq);
919- return 0;
920 }
921
922 if (!(survey->filled & SURVEY_HAS_CHAN_TIME)) {
923+ survey->channel_time = 0;
924 wpa_printf(MSG_INFO,
925 "ACS: Survey for freq %d is missing channel time",
926 survey->freq);
927- return 0;
928 }
929
930 if (!(survey->filled & SURVEY_HAS_CHAN_TIME_BUSY) &&
developer05f3b2b2024-08-19 19:17:34 +0800931@@ -489,7 +489,6 @@ static int acs_survey_is_sufficient(struct freq_survey *survey)
developer66e89bc2024-04-23 14:50:01 +0800932 wpa_printf(MSG_INFO,
933 "ACS: Survey for freq %d is missing RX and busy time (at least one is required)",
934 survey->freq);
935- return 0;
936 }
937
938 return 1;
939diff --git a/src/ap/airtime_policy.c b/src/ap/airtime_policy.c
940index 68443115f..26f11ad98 100644
941--- a/src/ap/airtime_policy.c
942+++ b/src/ap/airtime_policy.c
943@@ -112,8 +112,14 @@ static void set_sta_weights(struct hostapd_data *hapd, unsigned int weight)
944 {
945 struct sta_info *sta;
946
947- for (sta = hapd->sta_list; sta; sta = sta->next)
948- sta_set_airtime_weight(hapd, sta, weight);
949+ for (sta = hapd->sta_list; sta; sta = sta->next) {
950+ unsigned int sta_weight = weight;
951+
952+ if (sta->dyn_airtime_weight)
953+ sta_weight = (weight * sta->dyn_airtime_weight) / 256;
954+
955+ sta_set_airtime_weight(hapd, sta, sta_weight);
956+ }
957 }
958
959
960@@ -244,7 +250,10 @@ int airtime_policy_new_sta(struct hostapd_data *hapd, struct sta_info *sta)
961 unsigned int weight;
962
963 if (hapd->iconf->airtime_mode == AIRTIME_MODE_STATIC) {
964- weight = get_weight_for_sta(hapd, sta->addr);
965+ if (sta->dyn_airtime_weight)
966+ weight = sta->dyn_airtime_weight;
967+ else
968+ weight = get_weight_for_sta(hapd, sta->addr);
969 if (weight)
970 return sta_set_airtime_weight(hapd, sta, weight);
971 }
972diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
developer05f3b2b2024-08-19 19:17:34 +0800973index e6669e6a3..29a9ae7db 100644
developer66e89bc2024-04-23 14:50:01 +0800974--- a/src/ap/ap_config.h
975+++ b/src/ap/ap_config.h
976@@ -121,6 +121,7 @@ struct hostapd_ssid {
977 #define DYNAMIC_VLAN_OPTIONAL 1
978 #define DYNAMIC_VLAN_REQUIRED 2
979 int dynamic_vlan;
980+ int vlan_no_bridge;
981 #define DYNAMIC_VLAN_NAMING_WITHOUT_DEVICE 0
982 #define DYNAMIC_VLAN_NAMING_WITH_DEVICE 1
983 #define DYNAMIC_VLAN_NAMING_END 2
984@@ -282,6 +283,8 @@ struct airtime_sta_weight {
985 struct hostapd_bss_config {
986 char iface[IFNAMSIZ + 1];
987 char bridge[IFNAMSIZ + 1];
988+ char ft_iface[IFNAMSIZ + 1];
989+ char snoop_iface[IFNAMSIZ + 1];
990 char vlan_bridge[IFNAMSIZ + 1];
991 char wds_bridge[IFNAMSIZ + 1];
992 int bridge_hairpin; /* hairpin_mode on bridge members */
993@@ -307,6 +310,7 @@ struct hostapd_bss_config {
994 unsigned int eap_sim_db_timeout;
995 int eap_server_erp; /* Whether ERP is enabled on internal EAP server */
996 struct hostapd_ip_addr own_ip_addr;
997+ int dynamic_own_ip_addr;
998 char *nas_identifier;
999 struct hostapd_radius_servers *radius;
developer05f3b2b2024-08-19 19:17:34 +08001000 int radius_require_message_authenticator;
1001@@ -995,6 +999,35 @@ struct hostapd_bss_config {
1002 bool mld_indicate_disabled;
1003 #endif /* CONFIG_TESTING_OPTIONS */
1004 #endif /* CONFIG_IEEE80211BE */
1005+
1006+#ifdef CONFIG_APUP
1007+ /**
1008+ * Access Point Micro Peering
1009+ * A simpler and more useful successor to Ad Hoc,
1010+ * Wireless Distribution System, 802.11s mesh mode, Multi-AP and EasyMesh.
1011+ *
1012+ * Almost plain APs communicate between them via 4-address mode, like in WDS
1013+ * but all of them are AP, so they can eventually communicate also with
1014+ * plain stations and more AP nodes in sight.
1015+ * Low hardware requirements, just AP mode support + 4-address mode, and no
1016+ * more unnecessary complications, like hardcoded bridging or routing
1017+ * algorithm in WiFi stack.
1018+ * For each AP in sight an interface is created, and then it can be used as
1019+ * convenient in each case, bridging, routing etc.
1020+ */
1021+ bool apup;
1022+
1023+ /**
1024+ * In 4-address mode each peer AP in sight is associated to its own
1025+ * interface so we have more flexibility in "user-space".
1026+ * Those interfaces could be simply bridged in a trivial topology (which
1027+ * happens automatically if wds_bridge is not an empty string), or feeded to
1028+ * a routing daemon.
1029+ *
1030+ * If not defined interface names are generated following the WDS convention.
1031+ */
1032+ char apup_peer_ifname_prefix[IFNAMSIZ + 1];
1033+#endif /* CONFIG_APUP */
1034 };
1035
1036 /**
1037@@ -1085,6 +1118,8 @@ struct hostapd_config {
developer66e89bc2024-04-23 14:50:01 +08001038 unsigned int track_sta_max_num;
1039 unsigned int track_sta_max_age;
1040
1041+ int max_num_sta;
1042+
1043 char country[3]; /* first two octets: country code as described in
1044 * ISO/IEC 3166-1. Third octet:
1045 * ' ' (ascii 32): all environments
developer05f3b2b2024-08-19 19:17:34 +08001046@@ -1122,6 +1157,8 @@ struct hostapd_config {
developer66e89bc2024-04-23 14:50:01 +08001047
1048 int ht_op_mode_fixed;
1049 u16 ht_capab;
1050+ int noscan;
1051+ int no_ht_coex;
1052 int ieee80211n;
1053 int secondary_channel;
1054 int no_pri_sec_switch;
1055diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
developer05f3b2b2024-08-19 19:17:34 +08001056index c47349110..7c9527cd3 100644
developer66e89bc2024-04-23 14:50:01 +08001057--- a/src/ap/ap_drv_ops.c
1058+++ b/src/ap/ap_drv_ops.c
developer05f3b2b2024-08-19 19:17:34 +08001059@@ -385,13 +385,37 @@ int hostapd_set_wds_sta(struct hostapd_data *hapd, char *ifname_wds,
1060 const u8 *addr, int aid, int val)
1061 {
1062 const char *bridge = NULL;
1063+ char ifName[IFNAMSIZ + 1];
1064+
1065+ int mRet = 0;
1066
1067 if (hapd->driver == NULL || hapd->driver->set_wds_sta == NULL)
developer66e89bc2024-04-23 14:50:01 +08001068 return -1;
developer05f3b2b2024-08-19 19:17:34 +08001069+
1070+#ifdef CONFIG_APUP
1071+ if (hapd->conf->apup && hapd->conf->apup_peer_ifname_prefix[0]) {
1072+ mRet = os_snprintf(
1073+ ifName, sizeof(ifName), "%s%d",
1074+ hapd->conf->apup_peer_ifname_prefix, aid);
1075+ }
1076+ else
1077+#endif // def CONFIG_APUP
1078+ mRet = os_snprintf(
1079+ ifName, sizeof(ifName), "%s.sta%d",
1080+ hapd->conf->iface, aid);
1081+
1082+ if (mRet >= (int) sizeof(ifName))
1083+ wpa_printf(MSG_WARNING,
1084+ "nl80211: WDS interface name was truncated");
1085+ else if (mRet < 0)
1086+ return mRet;
1087+
1088+ // Pass back to the caller the resulting interface name
1089+ if (ifname_wds)
1090+ os_strlcpy(ifname_wds, ifName, IFNAMSIZ + 1);
1091+
developer66e89bc2024-04-23 14:50:01 +08001092 if (hapd->conf->wds_bridge[0])
1093 bridge = hapd->conf->wds_bridge;
1094- else if (hapd->conf->bridge[0])
1095- bridge = hapd->conf->bridge;
1096 return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val,
1097 bridge, ifname_wds);
1098 }
developer66e89bc2024-04-23 14:50:01 +08001099diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
developer05f3b2b2024-08-19 19:17:34 +08001100index d7e79c840..58ca046c6 100644
developer66e89bc2024-04-23 14:50:01 +08001101--- a/src/ap/ap_drv_ops.h
1102+++ b/src/ap/ap_drv_ops.h
developer05f3b2b2024-08-19 19:17:34 +08001103@@ -35,6 +35,9 @@ int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname,
1104 int enabled);
1105 int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname);
1106 int hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname);
1107+
1108+/** @param val as per nl80211 driver implementation, 1 means add 0 means remove
1109+ */
1110 int hostapd_set_wds_sta(struct hostapd_data *hapd, char *ifname_wds,
1111 const u8 *addr, int aid, int val);
1112 int hostapd_sta_add(struct hostapd_data *hapd,
1113@@ -371,12 +374,12 @@ static inline int hostapd_drv_br_port_set_attr(struct hostapd_data *hapd,
developer66e89bc2024-04-23 14:50:01 +08001114
1115 static inline int hostapd_drv_br_set_net_param(struct hostapd_data *hapd,
1116 enum drv_br_net_param param,
1117- unsigned int val)
1118+ const char *ifname, unsigned int val)
1119 {
1120 if (hapd->driver == NULL || hapd->drv_priv == NULL ||
1121 hapd->driver->br_set_net_param == NULL)
1122 return -1;
1123- return hapd->driver->br_set_net_param(hapd->drv_priv, param, val);
1124+ return hapd->driver->br_set_net_param(hapd->drv_priv, param, ifname, val);
1125 }
1126
1127 static inline int hostapd_drv_vendor_cmd(struct hostapd_data *hapd,
developer05f3b2b2024-08-19 19:17:34 +08001128@@ -404,6 +407,23 @@ static inline int hostapd_drv_stop_ap(struct hostapd_data *hapd)
developer66e89bc2024-04-23 14:50:01 +08001129 return hapd->driver->stop_ap(hapd->drv_priv, link_id);
1130 }
1131
1132+static inline int hostapd_drv_if_rename(struct hostapd_data *hapd,
1133+ enum wpa_driver_if_type type,
1134+ const char *ifname,
1135+ const char *new_name)
1136+{
1137+ if (!hapd->driver || !hapd->driver->if_rename || !hapd->drv_priv)
1138+ return -1;
1139+ return hapd->driver->if_rename(hapd->drv_priv, type, ifname, new_name);
1140+}
1141+
1142+static inline int hostapd_drv_set_first_bss(struct hostapd_data *hapd)
1143+{
1144+ if (!hapd->driver || !hapd->driver->set_first_bss || !hapd->drv_priv)
1145+ return 0;
1146+ return hapd->driver->set_first_bss(hapd->drv_priv);
1147+}
1148+
1149 static inline int hostapd_drv_channel_info(struct hostapd_data *hapd,
1150 struct wpa_channel_info *ci)
1151 {
developer05f3b2b2024-08-19 19:17:34 +08001152diff --git a/src/ap/apup.c b/src/ap/apup.c
1153new file mode 100644
1154index 000000000..f736ddc8e
1155--- /dev/null
1156+++ b/src/ap/apup.c
1157@@ -0,0 +1,168 @@
1158+/*
1159+ * hostapd / APuP Access Point Micro Peering
1160+ *
1161+ * Copyright (C) 2023-2024 Gioacchino Mazzurco <gio@polymathes.cc>
1162+ *
1163+ * This software may be distributed under the terms of the BSD license.
1164+ * See README for more details.
1165+ */
1166+
1167+/* Be extremely careful altering include order, move just one in the wrong place
1168+ * and you will start getting a bunch of error of undefined bool, size_t etc. */
1169+
1170+#include "utils/includes.h"
1171+#include "utils/common.h"
1172+#include "utils/os.h"
1173+
1174+#include "apup.h"
1175+
1176+#include "drivers/driver.h"
1177+#include "wpa_auth.h"
1178+#include "ap_mlme.h"
1179+#include "ieee802_11.h"
1180+#include "ap_drv_ops.h"
1181+#include "sta_info.h"
1182+
1183+#ifdef UBUS_SUPPORT
1184+# include "ubus.h"
1185+#endif
1186+
1187+#ifdef UCODE_SUPPORT
1188+# include "ucode.h"
1189+#endif
1190+
1191+void apup_process_beacon(struct hostapd_data *hapd,
1192+ const struct ieee80211_mgmt *mgmt, size_t len,
1193+ const struct ieee802_11_elems *elems )
1194+{
1195+ if (!os_memcmp(hapd->own_addr, mgmt->bssid, ETH_ALEN))
1196+ {
1197+ wpa_printf(MSG_WARNING,
1198+ "apup_process_beacon(...) own beacon elems.ssid %.*s",
1199+ (int) elems->ssid_len, elems->ssid);
1200+ return;
1201+ }
1202+
1203+ if (elems->ssid_len != hapd->conf->ssid.ssid_len ||
1204+ os_memcmp(elems->ssid, hapd->conf->ssid.ssid, elems->ssid_len))
1205+ return;
1206+
1207+ struct sta_info* sta_ret = ap_get_sta(hapd, mgmt->bssid);
1208+ if (sta_ret)
1209+ return;
1210+
1211+ sta_ret = ap_sta_add(hapd, mgmt->bssid);
1212+
1213+ /* TODO: this has been added just to making compiler happy after breaking
1214+ * changes introduced in 11a607d121df512e010148bedcb4263a03329dc7 to support
1215+ * IEEE80211BE Multi Link Operation. Look at that commit with more time and
1216+ * understand what could be a proper implementation in this context too
1217+ */
1218+ const u8 *mld_link_addr = NULL;
1219+ bool mld_link_sta = false;
1220+
1221+ /* First add the station without more information */
1222+ int aRet = hostapd_sta_add(
1223+ hapd, mgmt->bssid, sta_ret->aid, 0,
1224+ NULL, 0, 0, NULL, NULL, NULL, 0, NULL, 0, NULL,
1225+ sta_ret->flags, 0, 0, 0,
1226+ 0, // 0 add, 1 set
1227+ mld_link_addr, mld_link_sta);
1228+
1229+ sta_ret->flags |= WLAN_STA_AUTH;
1230+ wpa_auth_sm_event(sta_ret->wpa_sm, WPA_AUTH);
1231+
1232+ /* TODO: Investigate if supporting WPA or other encryption method is
1233+ * possible */
1234+ sta_ret->auth_alg = WLAN_AUTH_OPEN;
1235+ mlme_authenticate_indication(hapd, sta_ret);
1236+
1237+ sta_ret->capability = le_to_host16(mgmt->u.beacon.capab_info);
1238+
1239+ if (sta_ret->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1240+ sta_ret->flags |= WLAN_STA_SHORT_PREAMBLE;
1241+ else
1242+ sta_ret->flags &= ~WLAN_STA_SHORT_PREAMBLE;
1243+
1244+ hostapd_copy_supp_rates(hapd, sta_ret, elems);
1245+
1246+ /* Whithout this flag copy_sta_[v]ht_capab will disable [V]HT
1247+ * capabilities even if available */
1248+ if (elems->ht_capabilities || elems->vht_capabilities)
1249+ sta_ret->flags |= WLAN_STA_WMM;
1250+
1251+ copy_sta_ht_capab(hapd, sta_ret, elems->ht_capabilities);
1252+#ifdef CONFIG_IEEE80211AC
1253+ copy_sta_vht_capab(hapd, sta_ret, elems->vht_capabilities);
1254+ copy_sta_vht_oper(hapd, sta_ret, elems->vht_operation);
1255+ copy_sta_vendor_vht(hapd, sta_ret, elems->vendor_vht, elems->vendor_vht_len);
1256+#endif // def CONFIG_IEEE80211AC
1257+#ifdef CONFIG_IEEE80211AX
1258+ copy_sta_he_capab(hapd, sta_ret, IEEE80211_MODE_AP,
1259+ elems->he_capabilities, elems->he_capabilities_len);
1260+ copy_sta_he_6ghz_capab(hapd, sta_ret, elems->he_6ghz_band_cap);
1261+#endif // def CONFIG_IEEE80211AX
1262+#ifdef CONFIG_IEEE80211BE
1263+ copy_sta_eht_capab(hapd, sta_ret,
1264+ IEEE80211_MODE_AP, // TODO: Make sure is the right value
1265+ elems->he_capabilities, elems->he_capabilities_len,
1266+ elems->eht_capabilities, elems->eht_capabilities_len);
1267+#endif //def CONFIG_IEEE80211BE
1268+
1269+ update_ht_state(hapd, sta_ret);
1270+
1271+ if (hostapd_get_aid(hapd, sta_ret) < 0)
1272+ {
1273+ wpa_printf(MSG_INFO, "apup_process_beacon(...) No room for more AIDs");
1274+ return;
1275+ }
1276+
1277+ sta_ret->flags |= WLAN_STA_ASSOC_REQ_OK;
1278+
1279+ /* Make sure that the previously registered inactivity timer will not
1280+ * remove the STA immediately. */
1281+ sta_ret->timeout_next = STA_NULLFUNC;
1282+
1283+ sta_ret->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
1284+
1285+ /* Then set the paramethers */
1286+ int sRet = hostapd_sta_add(
1287+ hapd, mgmt->bssid, sta_ret->aid,
1288+ sta_ret->capability,
1289+ sta_ret->supported_rates, sta_ret->supported_rates_len,
1290+ 0, // u16 listen_interval TODO ?
1291+ sta_ret->ht_capabilities,
1292+ sta_ret->vht_capabilities,
1293+ sta_ret->he_capab, sta_ret->he_capab_len,
1294+ sta_ret->eht_capab, sta_ret->eht_capab_len,
1295+ sta_ret->he_6ghz_capab,
1296+ sta_ret->flags,
1297+ 0, // u8 qosinfo
1298+ sta_ret->vht_opmode,
1299+ 0, // int supp_p2p_ps
1300+ 1, // 0 add, 1 set
1301+ mld_link_addr, mld_link_sta);
1302+
1303+ ap_sta_set_authorized(hapd, sta_ret, 1);
1304+ hostapd_set_sta_flags(hapd, sta_ret);
1305+
1306+ char mIfname[IFNAMSIZ + 1];
1307+ os_memset(mIfname, 0, IFNAMSIZ + 1);
1308+
1309+ // last param 1 means add 0 means remove
1310+ int mRet = hostapd_set_wds_sta(
1311+ hapd, mIfname, mgmt->bssid, sta_ret->aid, 1);
1312+
1313+ wpa_printf(MSG_INFO,
1314+ "apup_process_beacon(...) Added APuP peer at %s with flags: %d,"
1315+ " capabilities %d",
1316+ mIfname, sta_ret->flags, sta_ret->capability);
1317+
1318+#ifdef UBUS_SUPPORT
1319+ hostapd_ubus_notify_apup_newpeer(hapd, mgmt->bssid, mIfname);
1320+#endif
1321+
1322+#ifdef UCODE_SUPPORT
1323+ hostapd_ucode_apup_newpeer(hapd, mIfname);
1324+#endif
1325+}
1326diff --git a/src/ap/apup.h b/src/ap/apup.h
1327new file mode 100644
1328index 000000000..a14a283bb
1329--- /dev/null
1330+++ b/src/ap/apup.h
1331@@ -0,0 +1,24 @@
1332+/*
1333+ * hostapd / APuP Access Point Micro Peering
1334+ *
1335+ * Copyright (C) 2023-2024 Gioacchino Mazzurco <gio@polymathes.cc>
1336+ *
1337+ * This software may be distributed under the terms of the BSD license.
1338+ * See README for more details.
1339+ */
1340+
1341+/* Be extremely careful altering include order, move just one in the wrong place
1342+ * and you will start getting a bunch of error of undefined bool, size_t etc. */
1343+
1344+#include "utils/includes.h"
1345+#include "utils/common.h"
1346+
1347+#include "hostapd.h"
1348+#include "common/ieee802_11_defs.h"
1349+
1350+/** When beacons from other Access Point are received, if the SSID is matching
1351+ * add them as APuP peers (aka WDS STA to our own AP) the same happens on the
1352+ * peer when receiving our beacons */
1353+void apup_process_beacon(struct hostapd_data *hapd,
1354+ const struct ieee80211_mgmt *mgmt, size_t len,
1355+ const struct ieee802_11_elems *elems );
developer66e89bc2024-04-23 14:50:01 +08001356diff --git a/src/ap/beacon.c b/src/ap/beacon.c
developer05f3b2b2024-08-19 19:17:34 +08001357index ddb99ca22..58b561661 100644
developer66e89bc2024-04-23 14:50:01 +08001358--- a/src/ap/beacon.c
1359+++ b/src/ap/beacon.c
developer05f3b2b2024-08-19 19:17:34 +08001360@@ -1439,6 +1439,12 @@ void handle_probe_req(struct hostapd_data *hapd,
developer66e89bc2024-04-23 14:50:01 +08001361 int mld_id;
1362 u16 links;
1363 #endif /* CONFIG_IEEE80211BE */
1364+ struct hostapd_ubus_request req = {
1365+ .type = HOSTAPD_UBUS_PROBE_REQ,
1366+ .mgmt_frame = mgmt,
1367+ .ssi_signal = ssi_signal,
1368+ .elems = &elems,
1369+ };
1370
1371 if (hapd->iconf->rssi_ignore_probe_request && ssi_signal &&
1372 ssi_signal < hapd->iconf->rssi_ignore_probe_request)
developer05f3b2b2024-08-19 19:17:34 +08001373@@ -1492,7 +1498,7 @@ void handle_probe_req(struct hostapd_data *hapd,
1374 * is less likely to see them (Probe Request frame sent on a
1375 * neighboring, but partially overlapping, channel).
1376 */
1377- if (elems.ds_params &&
1378+ if (elems.ds_params && 0 &&
1379 hapd->iface->current_mode &&
1380 (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G ||
1381 hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211B) &&
1382@@ -1625,6 +1631,12 @@ void handle_probe_req(struct hostapd_data *hapd,
developer66e89bc2024-04-23 14:50:01 +08001383 }
1384 #endif /* CONFIG_P2P */
1385
1386+ if (hostapd_ubus_handle_event(hapd, &req)) {
1387+ wpa_printf(MSG_DEBUG, "Probe request for " MACSTR " rejected by ubus handler.\n",
1388+ MAC2STR(mgmt->sa));
1389+ return;
1390+ }
1391+
1392 /* TODO: verify that supp_rates contains at least one matching rate
1393 * with AP configuration */
1394
developer05f3b2b2024-08-19 19:17:34 +08001395@@ -1643,7 +1655,7 @@ void handle_probe_req(struct hostapd_data *hapd,
developer66e89bc2024-04-23 14:50:01 +08001396 if (hapd->conf->no_probe_resp_if_max_sta &&
1397 is_multicast_ether_addr(mgmt->da) &&
1398 is_multicast_ether_addr(mgmt->bssid) &&
1399- hapd->num_sta >= hapd->conf->max_num_sta &&
1400+ hostapd_check_max_sta(hapd) &&
1401 !ap_get_sta(hapd, mgmt->sa)) {
1402 wpa_printf(MSG_MSGDUMP, "%s: Ignore Probe Request from " MACSTR
1403 " since no room for additional STA",
1404diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
developer05f3b2b2024-08-19 19:17:34 +08001405index d4d73de19..a1ddbda9f 100644
developer66e89bc2024-04-23 14:50:01 +08001406--- a/src/ap/ctrl_iface_ap.c
1407+++ b/src/ap/ctrl_iface_ap.c
1408@@ -26,6 +26,26 @@
1409 #include "taxonomy.h"
1410 #include "wnm_ap.h"
1411
1412+static const char * hw_mode_str(enum hostapd_hw_mode mode)
1413+{
1414+ switch (mode) {
1415+ case HOSTAPD_MODE_IEEE80211B:
1416+ return "b";
1417+ case HOSTAPD_MODE_IEEE80211G:
1418+ return "g";
1419+ case HOSTAPD_MODE_IEEE80211A:
1420+ return "a";
1421+ case HOSTAPD_MODE_IEEE80211AD:
1422+ return "ad";
1423+ case HOSTAPD_MODE_IEEE80211ANY:
1424+ return "any";
1425+ case NUM_HOSTAPD_MODES:
1426+ return "invalid";
1427+ }
1428+ return "unknown";
1429+}
1430+
1431+#ifdef CONFIG_CTRL_IFACE_MIB
1432
1433 static size_t hostapd_write_ht_mcs_bitmask(char *buf, size_t buflen,
1434 size_t curr_len, const u8 *mcs_set)
1435@@ -212,26 +232,6 @@ static const char * timeout_next_str(int val)
1436 }
1437
1438
1439-static const char * hw_mode_str(enum hostapd_hw_mode mode)
1440-{
1441- switch (mode) {
1442- case HOSTAPD_MODE_IEEE80211B:
1443- return "b";
1444- case HOSTAPD_MODE_IEEE80211G:
1445- return "g";
1446- case HOSTAPD_MODE_IEEE80211A:
1447- return "a";
1448- case HOSTAPD_MODE_IEEE80211AD:
1449- return "ad";
1450- case HOSTAPD_MODE_IEEE80211ANY:
1451- return "any";
1452- case NUM_HOSTAPD_MODES:
1453- return "invalid";
1454- }
1455- return "unknown";
1456-}
1457-
1458-
1459 static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
1460 struct sta_info *sta,
1461 char *buf, size_t buflen)
developer05f3b2b2024-08-19 19:17:34 +08001462@@ -562,6 +562,7 @@ int hostapd_ctrl_iface_sta_next(struct hostapd_data *hapd, const char *txtaddr,
developer66e89bc2024-04-23 14:50:01 +08001463 return hostapd_ctrl_iface_sta_mib(hapd, sta->next, buf, buflen);
1464 }
1465
1466+#endif
1467
1468 #ifdef CONFIG_P2P_MANAGER
1469 static int p2p_manager_disconnect(struct hostapd_data *hapd, u16 stype,
developer05f3b2b2024-08-19 19:17:34 +08001470@@ -1010,12 +1011,12 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
developer66e89bc2024-04-23 14:50:01 +08001471 return len;
1472 len += ret;
1473 }
1474-
1475+#ifdef CONFIG_CTRL_IFACE_MIB
1476 if (iface->conf->ieee80211n && !hapd->conf->disable_11n && mode) {
1477 len = hostapd_write_ht_mcs_bitmask(buf, buflen, len,
1478 mode->mcs_set);
1479 }
1480-
1481+#endif /* CONFIG_CTRL_IFACE_MIB */
1482 if (iface->current_rates && iface->num_rates) {
1483 ret = os_snprintf(buf + len, buflen - len, "supported_rates=");
1484 if (os_snprintf_error(buflen - len, ret))
1485diff --git a/src/ap/dfs.c b/src/ap/dfs.c
developer05f3b2b2024-08-19 19:17:34 +08001486index af9dc16f5..fe044297b 100644
developer66e89bc2024-04-23 14:50:01 +08001487--- a/src/ap/dfs.c
1488+++ b/src/ap/dfs.c
developer05f3b2b2024-08-19 19:17:34 +08001489@@ -18,6 +18,7 @@
developer66e89bc2024-04-23 14:50:01 +08001490 #include "ap_drv_ops.h"
1491 #include "drivers/driver.h"
1492 #include "dfs.h"
1493+#include "crypto/crypto.h"
1494
1495
1496 enum dfs_channel_type {
developer05f3b2b2024-08-19 19:17:34 +08001497@@ -527,9 +528,14 @@ dfs_get_valid_channel(struct hostapd_iface *iface,
developer66e89bc2024-04-23 14:50:01 +08001498 int num_available_chandefs;
1499 int chan_idx, chan_idx2;
1500 int sec_chan_idx_80p80 = -1;
1501+ bool is_mesh = false;
1502 int i;
1503 u32 _rand;
1504
1505+#ifdef CONFIG_MESH
1506+ is_mesh = iface->mconf;
1507+#endif
1508+
1509 wpa_printf(MSG_DEBUG, "DFS: Selecting random channel");
1510 *secondary_channel = 0;
1511 *oper_centr_freq_seg0_idx = 0;
developer05f3b2b2024-08-19 19:17:34 +08001512@@ -549,8 +555,20 @@ dfs_get_valid_channel(struct hostapd_iface *iface,
developer66e89bc2024-04-23 14:50:01 +08001513 if (num_available_chandefs == 0)
1514 return NULL;
1515
1516- if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0)
1517+ /* try to use deterministic channel in mesh, so that both sides
1518+ * have a chance to switch to the same channel */
1519+ if (is_mesh) {
1520+#ifdef CONFIG_MESH
1521+ u64 hash[4];
1522+ const u8 *meshid[1] = { &iface->mconf->meshid[0] };
1523+ const size_t meshid_len = iface->mconf->meshid_len;
1524+
1525+ sha256_vector(1, meshid, &meshid_len, (u8 *)&hash[0]);
1526+ _rand = hash[0] + hash[1] + hash[2] + hash[3];
1527+#endif
1528+ } else if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0)
1529 return NULL;
1530+
1531 chan_idx = _rand % num_available_chandefs;
1532 wpa_printf(MSG_DEBUG, "DFS: Picked random entry from the list: %d/%d",
1533 chan_idx, num_available_chandefs);
developer05f3b2b2024-08-19 19:17:34 +08001534@@ -1218,6 +1236,8 @@ int hostapd_dfs_pre_cac_expired(struct hostapd_iface *iface, int freq,
developer66e89bc2024-04-23 14:50:01 +08001535 "freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d",
1536 freq, ht_enabled, chan_offset, chan_width, cf1, cf2);
1537
1538+ hostapd_ubus_notify_radar_detected(iface, freq, chan_width, cf1, cf2);
1539+
1540 /* Proceed only if DFS is not offloaded to the driver */
1541 if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)
1542 return 0;
1543diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
developer05f3b2b2024-08-19 19:17:34 +08001544index c74e551c5..6e76f697a 100644
developer66e89bc2024-04-23 14:50:01 +08001545--- a/src/ap/drv_callbacks.c
1546+++ b/src/ap/drv_callbacks.c
developer05f3b2b2024-08-19 19:17:34 +08001547@@ -270,6 +270,10 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
developer66e89bc2024-04-23 14:50:01 +08001548 struct hostapd_iface *iface = hapd->iface;
1549 #endif /* CONFIG_OWE */
1550 bool updated = false;
1551+ struct hostapd_ubus_request req = {
1552+ .type = HOSTAPD_UBUS_ASSOC_REQ,
1553+ .addr = addr,
1554+ };
1555
1556 if (addr == NULL) {
1557 /*
developer05f3b2b2024-08-19 19:17:34 +08001558@@ -414,6 +418,12 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
developer66e89bc2024-04-23 14:50:01 +08001559 goto fail;
1560 }
1561
1562+ if (hostapd_ubus_handle_event(hapd, &req)) {
1563+ wpa_printf(MSG_DEBUG, "Station " MACSTR " assoc rejected by ubus handler.\n",
1564+ MAC2STR(req.addr));
1565+ goto fail;
1566+ }
1567+
1568 #ifdef CONFIG_P2P
1569 if (elems.p2p) {
1570 wpabuf_free(sta->p2p_ie);
developer05f3b2b2024-08-19 19:17:34 +08001571@@ -2416,8 +2426,8 @@ static void hostapd_event_color_change(struct hostapd_data *hapd, bool success)
1572 #endif /* CONFIG_IEEE80211AX */
1573
developer66e89bc2024-04-23 14:50:01 +08001574
1575-void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
1576- union wpa_event_data *data)
1577+void hostapd_wpa_event(void *ctx, enum wpa_event_type event,
1578+ union wpa_event_data *data)
1579 {
1580 struct hostapd_data *hapd = ctx;
1581 struct sta_info *sta;
developer05f3b2b2024-08-19 19:17:34 +08001582@@ -2776,7 +2786,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
developer66e89bc2024-04-23 14:50:01 +08001583 }
1584
1585
1586-void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
1587+void hostapd_wpa_event_global(void *ctx, enum wpa_event_type event,
1588 union wpa_event_data *data)
1589 {
1590 struct hapd_interfaces *interfaces = ctx;
1591diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
developer05f3b2b2024-08-19 19:17:34 +08001592index 5a8cdc90e..8159194e1 100644
developer66e89bc2024-04-23 14:50:01 +08001593--- a/src/ap/hostapd.c
1594+++ b/src/ap/hostapd.c
1595@@ -247,6 +247,29 @@ static int hostapd_iface_conf_changed(struct hostapd_config *newconf,
1596 return 0;
1597 }
1598
1599+static inline int hostapd_iface_num_sta(struct hostapd_iface *iface)
1600+{
1601+ int num_sta = 0;
1602+ int i;
1603+
1604+ for (i = 0; i < iface->num_bss; i++)
1605+ num_sta += iface->bss[i]->num_sta;
1606+
1607+ return num_sta;
1608+}
1609+
1610+
1611+int hostapd_check_max_sta(struct hostapd_data *hapd)
1612+{
1613+ if (hapd->num_sta >= hapd->conf->max_num_sta)
1614+ return 1;
1615+
1616+ if (hapd->iconf->max_num_sta &&
1617+ hostapd_iface_num_sta(hapd->iface) >= hapd->iconf->max_num_sta)
1618+ return 1;
1619+
1620+ return 0;
1621+}
1622
1623 int hostapd_reload_config(struct hostapd_iface *iface)
1624 {
1625@@ -255,6 +278,8 @@ int hostapd_reload_config(struct hostapd_iface *iface)
1626 struct hostapd_config *newconf, *oldconf;
1627 size_t j;
1628
1629+ hostapd_ucode_reload_bss(hapd);
1630+
1631 if (iface->config_fname == NULL) {
1632 /* Only in-memory config in use - assume it has been updated */
1633 hostapd_clear_old(iface);
1634@@ -475,6 +500,8 @@ void hostapd_free_hapd_data(struct hostapd_data *hapd)
1635 hapd->beacon_set_done = 0;
1636
1637 wpa_printf(MSG_DEBUG, "%s(%s)", __func__, hapd->conf->iface);
1638+ hostapd_ucode_free_bss(hapd);
1639+ hostapd_ubus_free_bss(hapd);
1640 accounting_deinit(hapd);
1641 hostapd_deinit_wpa(hapd);
1642 vlan_deinit(hapd);
developer05f3b2b2024-08-19 19:17:34 +08001643@@ -485,7 +512,7 @@ void hostapd_free_hapd_data(struct hostapd_data *hapd)
1644 struct hapd_interfaces *ifaces = hapd->iface->interfaces;
1645 size_t i;
1646
1647- for (i = 0; i < ifaces->count; i++) {
1648+ for (i = 0; ifaces && i < ifaces->count; i++) {
1649 struct hostapd_iface *iface = ifaces->iface[i];
1650 size_t j;
1651
developer66e89bc2024-04-23 14:50:01 +08001652@@ -685,6 +712,7 @@ static void sta_track_deinit(struct hostapd_iface *iface)
1653 void hostapd_cleanup_iface_partial(struct hostapd_iface *iface)
1654 {
1655 wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
developer05f3b2b2024-08-19 19:17:34 +08001656+ hostapd_ucode_free_iface(iface);
1657 eloop_cancel_timeout(channel_list_update_timeout, iface, NULL);
developer66e89bc2024-04-23 14:50:01 +08001658 #ifdef NEED_AP_MLME
1659 hostapd_stop_setup_timers(iface);
developer05f3b2b2024-08-19 19:17:34 +08001660@@ -1304,6 +1332,9 @@ static int hostapd_start_beacon(struct hostapd_data *hapd,
developer66e89bc2024-04-23 14:50:01 +08001661 if (hapd->driver && hapd->driver->set_operstate)
1662 hapd->driver->set_operstate(hapd->drv_priv, 1);
1663
1664+ hostapd_ubus_add_bss(hapd);
1665+ hostapd_ucode_add_bss(hapd);
1666+
1667 return 0;
1668 }
1669
developer05f3b2b2024-08-19 19:17:34 +08001670@@ -1336,6 +1367,7 @@ static int hostapd_bss_radius_init(struct hostapd_data *hapd)
1671
1672 os_memset(&das_conf, 0, sizeof(das_conf));
1673 das_conf.port = conf->radius_das_port;
1674+ das_conf.nas_identifier = conf->nas_identifier;
1675 das_conf.shared_secret = conf->radius_das_shared_secret;
1676 das_conf.shared_secret_len =
1677 conf->radius_das_shared_secret_len;
1678@@ -1378,8 +1410,7 @@ static int hostapd_bss_radius_init(struct hostapd_data *hapd)
developer66e89bc2024-04-23 14:50:01 +08001679 * initialized. Most of the modules that are initialized here will be
1680 * deinitialized in hostapd_cleanup().
1681 */
1682-static int hostapd_setup_bss(struct hostapd_data *hapd, int first,
1683- bool start_beacon)
1684+int hostapd_setup_bss(struct hostapd_data *hapd, int first, bool start_beacon)
1685 {
1686 struct hostapd_bss_config *conf = hapd->conf;
1687 u8 ssid[SSID_MAX_LEN + 1];
developer05f3b2b2024-08-19 19:17:34 +08001688@@ -2510,6 +2541,7 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
developer66e89bc2024-04-23 14:50:01 +08001689 if (err)
1690 goto fail;
1691
1692+ hostapd_ubus_add_iface(iface);
1693 wpa_printf(MSG_DEBUG, "Completing interface initialization");
1694 if (iface->freq) {
1695 #ifdef NEED_AP_MLME
developer05f3b2b2024-08-19 19:17:34 +08001696@@ -2739,6 +2771,7 @@ dfs_offload:
developer66e89bc2024-04-23 14:50:01 +08001697
1698 fail:
1699 wpa_printf(MSG_ERROR, "Interface initialization failed");
1700+ hostapd_ubus_free_iface(iface);
1701
1702 if (iface->is_no_ir) {
1703 hostapd_set_state(iface, HAPD_IFACE_NO_IR);
developer05f3b2b2024-08-19 19:17:34 +08001704@@ -2938,7 +2971,7 @@ hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface,
developer66e89bc2024-04-23 14:50:01 +08001705 }
1706
1707
1708-static void hostapd_bss_deinit(struct hostapd_data *hapd)
1709+void hostapd_bss_deinit(struct hostapd_data *hapd)
1710 {
1711 if (!hapd)
1712 return;
developer05f3b2b2024-08-19 19:17:34 +08001713@@ -3471,6 +3504,7 @@ void hostapd_interface_deinit_free(struct hostapd_iface *iface)
developer66e89bc2024-04-23 14:50:01 +08001714 (unsigned int) iface->conf->num_bss);
1715 driver = iface->bss[0]->driver;
1716 drv_priv = iface->bss[0]->drv_priv;
1717+ hostapd_ubus_free_iface(iface);
1718 hostapd_interface_deinit(iface);
1719 wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit",
1720 __func__, driver, drv_priv);
developer05f3b2b2024-08-19 19:17:34 +08001721@@ -4002,7 +4036,8 @@ int hostapd_remove_iface(struct hapd_interfaces *interfaces, char *buf)
developer66e89bc2024-04-23 14:50:01 +08001722 hapd_iface = interfaces->iface[i];
1723 if (hapd_iface == NULL)
1724 return -1;
1725- if (!os_strcmp(hapd_iface->conf->bss[0]->iface, buf)) {
1726+ if (!os_strcmp(hapd_iface->phy, buf) ||
1727+ !os_strcmp(hapd_iface->conf->bss[0]->iface, buf)) {
1728 wpa_printf(MSG_INFO, "Remove interface '%s'", buf);
1729 hapd_iface->driver_ap_teardown =
1730 !!(hapd_iface->drv_flags &
developer05f3b2b2024-08-19 19:17:34 +08001731@@ -4048,6 +4083,8 @@ int hostapd_remove_iface(struct hapd_interfaces *interfaces, char *buf)
developer66e89bc2024-04-23 14:50:01 +08001732 void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
1733 int reassoc)
1734 {
1735+ int mld_assoc_link_id = -1;
1736+
1737 if (hapd->tkip_countermeasures) {
1738 hostapd_drv_sta_deauth(hapd, sta->addr,
1739 WLAN_REASON_MICHAEL_MIC_FAILURE);
developer05f3b2b2024-08-19 19:17:34 +08001740@@ -4055,10 +4092,16 @@ void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
1741 }
1742
1743 #ifdef CONFIG_IEEE80211BE
1744- if (ap_sta_is_mld(hapd, sta) &&
1745- sta->mld_assoc_link_id != hapd->mld_link_id)
1746- return;
1747+ if (ap_sta_is_mld(hapd, sta)) {
1748+ if (sta->mld_assoc_link_id == hapd->mld_link_id) {
1749+ mld_assoc_link_id = sta->mld_assoc_link_id;
1750+ } else {
1751+ return;
1752+ }
1753+ }
developer66e89bc2024-04-23 14:50:01 +08001754 #endif /* CONFIG_IEEE80211BE */
1755+ if (mld_assoc_link_id != -2)
1756+ hostapd_prune_associations(hapd, sta->addr, mld_assoc_link_id);
1757
1758 ap_sta_clear_disconnect_timeouts(hapd, sta);
1759 sta->post_csa_sa_query = 0;
1760diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
developer05f3b2b2024-08-19 19:17:34 +08001761index 996977fdf..994e4681e 100644
developer66e89bc2024-04-23 14:50:01 +08001762--- a/src/ap/hostapd.h
1763+++ b/src/ap/hostapd.h
developer05f3b2b2024-08-19 19:17:34 +08001764@@ -18,6 +18,8 @@
developer66e89bc2024-04-23 14:50:01 +08001765 #include "utils/list.h"
1766 #include "ap_config.h"
1767 #include "drivers/driver.h"
1768+#include "ubus.h"
1769+#include "ucode.h"
1770
1771 #define OCE_STA_CFON_ENABLED(hapd) \
1772 ((hapd->conf->oce & OCE_STA_CFON) && \
developer05f3b2b2024-08-19 19:17:34 +08001773@@ -51,6 +53,10 @@ struct hapd_interfaces {
developer66e89bc2024-04-23 14:50:01 +08001774 struct hostapd_config * (*config_read_cb)(const char *config_fname);
1775 int (*ctrl_iface_init)(struct hostapd_data *hapd);
1776 void (*ctrl_iface_deinit)(struct hostapd_data *hapd);
1777+ int (*ctrl_iface_recv)(struct hostapd_data *hapd,
1778+ char *buf, char *reply, int reply_size,
1779+ struct sockaddr_storage *from,
1780+ socklen_t fromlen);
1781 int (*for_each_interface)(struct hapd_interfaces *interfaces,
1782 int (*cb)(struct hostapd_iface *iface,
1783 void *ctx), void *ctx);
developer05f3b2b2024-08-19 19:17:34 +08001784@@ -169,6 +175,21 @@ struct hostapd_sae_commit_queue {
developer66e89bc2024-04-23 14:50:01 +08001785 u8 msg[];
1786 };
1787
1788+/**
1789+ * struct hostapd_openwrt_stats - OpenWrt custom STA/AP statistics
1790+ */
1791+struct hostapd_openwrt_stats {
1792+ struct {
1793+ u64 neighbor_report_tx;
1794+ } rrm;
1795+
1796+ struct {
1797+ u64 bss_transition_query_rx;
1798+ u64 bss_transition_request_tx;
1799+ u64 bss_transition_response_rx;
1800+ } wnm;
1801+};
1802+
1803 /**
1804 * struct hostapd_data - hostapd per-BSS data structure
1805 */
developer05f3b2b2024-08-19 19:17:34 +08001806@@ -176,6 +197,8 @@ struct hostapd_data {
developer66e89bc2024-04-23 14:50:01 +08001807 struct hostapd_iface *iface;
1808 struct hostapd_config *iconf;
1809 struct hostapd_bss_config *conf;
1810+ struct hostapd_ubus_bss ubus;
1811+ struct hostapd_ucode_bss ucode;
1812 int interface_added; /* virtual interface added for this BSS */
1813 unsigned int started:1;
1814 unsigned int disabled:1;
developer05f3b2b2024-08-19 19:17:34 +08001815@@ -183,6 +206,9 @@ struct hostapd_data {
developer66e89bc2024-04-23 14:50:01 +08001816
1817 u8 own_addr[ETH_ALEN];
1818
1819+ /* OpenWrt specific statistics */
1820+ struct hostapd_openwrt_stats openwrt_stats;
1821+
1822 int num_sta; /* number of entries in sta_list */
1823 struct sta_info *sta_list; /* STA info list head */
1824 #define STA_HASH_SIZE 256
developer05f3b2b2024-08-19 19:17:34 +08001825@@ -535,6 +561,7 @@ struct hostapd_mld {
developer66e89bc2024-04-23 14:50:01 +08001826 */
1827 struct hostapd_iface {
1828 struct hapd_interfaces *interfaces;
1829+ struct hostapd_ucode_iface ucode;
1830 void *owner;
1831 char *config_fname;
1832 struct hostapd_config *conf;
developer05f3b2b2024-08-19 19:17:34 +08001833@@ -786,6 +813,7 @@ hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface,
developer66e89bc2024-04-23 14:50:01 +08001834 struct hostapd_bss_config *bss);
1835 int hostapd_setup_interface(struct hostapd_iface *iface);
1836 int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err);
1837+void hostapd_set_own_neighbor_report(struct hostapd_data *hapd);
1838 void hostapd_interface_deinit(struct hostapd_iface *iface);
1839 void hostapd_interface_free(struct hostapd_iface *iface);
1840 struct hostapd_iface * hostapd_alloc_iface(void);
developer05f3b2b2024-08-19 19:17:34 +08001841@@ -794,6 +822,8 @@ struct hostapd_iface * hostapd_init(struct hapd_interfaces *interfaces,
developer66e89bc2024-04-23 14:50:01 +08001842 struct hostapd_iface *
1843 hostapd_interface_init_bss(struct hapd_interfaces *interfaces, const char *phy,
1844 const char *config_fname, int debug);
1845+int hostapd_setup_bss(struct hostapd_data *hapd, int first, bool start_beacon);
1846+void hostapd_bss_deinit(struct hostapd_data *hapd);
1847 void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
1848 int reassoc);
1849 void hostapd_interface_deinit_free(struct hostapd_iface *iface);
developer05f3b2b2024-08-19 19:17:34 +08001850@@ -821,6 +851,7 @@ void hostapd_cleanup_cs_params(struct hostapd_data *hapd);
developer66e89bc2024-04-23 14:50:01 +08001851 void hostapd_periodic_iface(struct hostapd_iface *iface);
1852 int hostapd_owe_trans_get_info(struct hostapd_data *hapd);
1853 void hostapd_ocv_check_csa_sa_query(void *eloop_ctx, void *timeout_ctx);
1854+int hostapd_check_max_sta(struct hostapd_data *hapd);
1855
1856 void hostapd_switch_color(struct hostapd_data *hapd, u64 bitmap);
1857 void hostapd_cleanup_cca_params(struct hostapd_data *hapd);
developer05f3b2b2024-08-19 19:17:34 +08001858@@ -908,6 +939,16 @@ static inline bool hostapd_mld_is_first_bss(struct hostapd_data *hapd)
developer66e89bc2024-04-23 14:50:01 +08001859
developer05f3b2b2024-08-19 19:17:34 +08001860 #endif /* CONFIG_IEEE80211BE */
developer66e89bc2024-04-23 14:50:01 +08001861
1862+static inline bool ap_sta_is_mld(struct hostapd_data *hapd,
1863+ struct sta_info *sta)
1864+{
1865+#ifdef CONFIG_IEEE80211BE
1866+ return hapd->conf->mld_ap && sta && sta->mld_info.mld_sta;
1867+#else /* CONFIG_IEEE80211BE */
1868+ return false;
1869+#endif /* CONFIG_IEEE80211BE */
1870+}
1871+
developer05f3b2b2024-08-19 19:17:34 +08001872 u16 hostapd_get_punct_bitmap(struct hostapd_data *hapd);
1873
developer66e89bc2024-04-23 14:50:01 +08001874 #endif /* HOSTAPD_H */
1875diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
developer05f3b2b2024-08-19 19:17:34 +08001876index 8aa0b3ab5..400c50988 100644
developer66e89bc2024-04-23 14:50:01 +08001877--- a/src/ap/hw_features.c
1878+++ b/src/ap/hw_features.c
developer05f3b2b2024-08-19 19:17:34 +08001879@@ -553,7 +553,8 @@ static int ieee80211n_check_40mhz(struct hostapd_iface *iface)
developer66e89bc2024-04-23 14:50:01 +08001880 int ret;
1881
1882 /* Check that HT40 is used and PRI / SEC switch is allowed */
1883- if (!iface->conf->secondary_channel || iface->conf->no_pri_sec_switch)
1884+ if (!iface->conf->secondary_channel || iface->conf->no_pri_sec_switch ||
1885+ iface->conf->noscan)
1886 return 0;
1887
1888 hostapd_set_state(iface, HAPD_IFACE_HT_SCAN);
1889diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
developer05f3b2b2024-08-19 19:17:34 +08001890index d8d82d737..39b1bb4c7 100644
developer66e89bc2024-04-23 14:50:01 +08001891--- a/src/ap/ieee802_11.c
1892+++ b/src/ap/ieee802_11.c
developer05f3b2b2024-08-19 19:17:34 +08001893@@ -59,6 +59,9 @@
1894 #include "nan_usd_ap.h"
1895 #include "pasn/pasn_common.h"
1896
1897+#ifdef CONFIG_APUP
1898+# include "apup.h"
1899+#endif // def CONFIG_APUP
1900
1901 #ifdef CONFIG_FILS
1902 static struct wpabuf *
1903@@ -2876,7 +2879,7 @@ static void handle_auth(struct hostapd_data *hapd,
developer66e89bc2024-04-23 14:50:01 +08001904 u16 auth_alg, auth_transaction, status_code;
1905 u16 resp = WLAN_STATUS_SUCCESS;
1906 struct sta_info *sta = NULL;
1907- int res, reply_res;
1908+ int res, reply_res, ubus_resp;
1909 u16 fc;
1910 const u8 *challenge = NULL;
1911 u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
developer05f3b2b2024-08-19 19:17:34 +08001912@@ -2887,6 +2890,11 @@ static void handle_auth(struct hostapd_data *hapd,
developer66e89bc2024-04-23 14:50:01 +08001913 #ifdef CONFIG_IEEE80211BE
1914 bool mld_sta = false;
1915 #endif /* CONFIG_IEEE80211BE */
1916+ struct hostapd_ubus_request req = {
1917+ .type = HOSTAPD_UBUS_AUTH_REQ,
1918+ .mgmt_frame = mgmt,
1919+ .ssi_signal = rssi,
1920+ };
1921
1922 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
1923 wpa_printf(MSG_INFO, "handle_auth - too short payload (len=%lu)",
developer05f3b2b2024-08-19 19:17:34 +08001924@@ -3083,6 +3091,13 @@ static void handle_auth(struct hostapd_data *hapd,
developer66e89bc2024-04-23 14:50:01 +08001925 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1926 goto fail;
1927 }
1928+ ubus_resp = hostapd_ubus_handle_event(hapd, &req);
1929+ if (ubus_resp) {
1930+ wpa_printf(MSG_DEBUG, "Station " MACSTR " rejected by ubus handler.\n",
1931+ MAC2STR(mgmt->sa));
1932+ resp = ubus_resp > 0 ? (u16) ubus_resp : WLAN_STATUS_UNSPECIFIED_FAILURE;
1933+ goto fail;
1934+ }
1935 if (res == HOSTAPD_ACL_PENDING)
1936 return;
1937
developer05f3b2b2024-08-19 19:17:34 +08001938@@ -3555,8 +3570,8 @@ static u16 check_multi_ap(struct hostapd_data *hapd, struct sta_info *sta,
1939 }
1940
1941
1942-static u16 copy_supp_rates(struct hostapd_data *hapd, struct sta_info *sta,
1943- struct ieee802_11_elems *elems)
1944+u16 hostapd_copy_supp_rates(struct hostapd_data *hapd, struct sta_info *sta,
1945+ const struct ieee802_11_elems *elems)
1946 {
1947 /* Supported rates not used in IEEE 802.11ad/DMG */
1948 if (hapd->iface->current_mode &&
1949@@ -3943,7 +3958,7 @@ static int __check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
1950 elems->ext_capab_len);
1951 if (resp != WLAN_STATUS_SUCCESS)
1952 return resp;
1953- resp = copy_supp_rates(hapd, sta, elems);
1954+ resp = hostapd_copy_supp_rates(hapd, sta, elems);
1955 if (resp != WLAN_STATUS_SUCCESS)
1956 return resp;
1957
1958@@ -4763,6 +4778,13 @@ static int add_associated_sta(struct hostapd_data *hapd,
developer66e89bc2024-04-23 14:50:01 +08001959 * drivers to accept the STA parameter configuration. Since this is
1960 * after a new FT-over-DS exchange, a new TK has been derived, so key
1961 * reinstallation is not a concern for this case.
1962+ *
1963+ * If the STA was associated and authorized earlier, but came for a new
1964+ * connection (!added_unassoc + !reassoc), remove the existing STA entry
1965+ * so that it can be re-added. This case is rarely seen when the AP could
1966+ * not receive the deauth/disassoc frame from the STA. And the STA comes
1967+ * back with new connection within a short period or before the inactive
1968+ * STA entry is removed from the list.
1969 */
1970 wpa_printf(MSG_DEBUG, "Add associated STA " MACSTR
1971 " (added_unassoc=%d auth_alg=%u ft_over_ds=%u reassoc=%d authorized=%d ft_tk=%d fils_tk=%d)",
developer05f3b2b2024-08-19 19:17:34 +08001972@@ -4776,7 +4798,8 @@ static int add_associated_sta(struct hostapd_data *hapd,
developer66e89bc2024-04-23 14:50:01 +08001973 (!(sta->flags & WLAN_STA_AUTHORIZED) ||
1974 (reassoc && sta->ft_over_ds && sta->auth_alg == WLAN_AUTH_FT) ||
1975 (!wpa_auth_sta_ft_tk_already_set(sta->wpa_sm) &&
1976- !wpa_auth_sta_fils_tk_already_set(sta->wpa_sm)))) {
1977+ !wpa_auth_sta_fils_tk_already_set(sta->wpa_sm)) ||
1978+ (!reassoc && (sta->flags & WLAN_STA_AUTHORIZED)))) {
1979 hostapd_drv_sta_remove(hapd, sta->addr);
1980 wpa_auth_sm_event(sta->wpa_sm, WPA_DRV_STA_REMOVED);
1981 set = 0;
developer05f3b2b2024-08-19 19:17:34 +08001982@@ -5337,7 +5360,7 @@ static void handle_assoc(struct hostapd_data *hapd,
developer66e89bc2024-04-23 14:50:01 +08001983 int resp = WLAN_STATUS_SUCCESS;
1984 u16 reply_res = WLAN_STATUS_UNSPECIFIED_FAILURE;
1985 const u8 *pos;
1986- int left, i;
1987+ int left, i, ubus_resp;
1988 struct sta_info *sta;
1989 u8 *tmp = NULL;
1990 #ifdef CONFIG_FILS
developer05f3b2b2024-08-19 19:17:34 +08001991@@ -5579,6 +5602,11 @@ static void handle_assoc(struct hostapd_data *hapd,
developer66e89bc2024-04-23 14:50:01 +08001992 left = res;
1993 }
1994 #endif /* CONFIG_FILS */
1995+ struct hostapd_ubus_request req = {
1996+ .type = HOSTAPD_UBUS_ASSOC_REQ,
1997+ .mgmt_frame = mgmt,
1998+ .ssi_signal = rssi,
1999+ };
2000
2001 /* followed by SSID and Supported rates; and HT capabilities if 802.11n
2002 * is used */
developer05f3b2b2024-08-19 19:17:34 +08002003@@ -5681,6 +5709,13 @@ static void handle_assoc(struct hostapd_data *hapd,
developer66e89bc2024-04-23 14:50:01 +08002004 if (set_beacon)
developer05f3b2b2024-08-19 19:17:34 +08002005 ieee802_11_update_beacons(hapd->iface);
developer66e89bc2024-04-23 14:50:01 +08002006
2007+ ubus_resp = hostapd_ubus_handle_event(hapd, &req);
2008+ if (ubus_resp) {
2009+ wpa_printf(MSG_DEBUG, "Station " MACSTR " assoc rejected by ubus handler.\n",
2010+ MAC2STR(mgmt->sa));
2011+ resp = ubus_resp > 0 ? (u16) ubus_resp : WLAN_STATUS_UNSPECIFIED_FAILURE;
2012+ goto fail;
2013+ }
2014 fail:
2015
2016 /*
developer05f3b2b2024-08-19 19:17:34 +08002017@@ -5910,6 +5945,7 @@ static void handle_disassoc(struct hostapd_data *hapd,
developer66e89bc2024-04-23 14:50:01 +08002018 (unsigned long) len);
2019 return;
2020 }
2021+ hostapd_ubus_notify(hapd, "disassoc", mgmt->sa);
2022
2023 sta = ap_get_sta(hapd, mgmt->sa);
2024 if (!sta) {
developer05f3b2b2024-08-19 19:17:34 +08002025@@ -5941,6 +5977,8 @@ static void handle_deauth(struct hostapd_data *hapd,
developer66e89bc2024-04-23 14:50:01 +08002026 /* Clear the PTKSA cache entries for PASN */
2027 ptksa_cache_flush(hapd->ptksa, mgmt->sa, WPA_CIPHER_NONE);
2028
2029+ hostapd_ubus_notify(hapd, "deauth", mgmt->sa);
2030+
2031 sta = ap_get_sta(hapd, mgmt->sa);
2032 if (!sta) {
2033 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR
developer05f3b2b2024-08-19 19:17:34 +08002034@@ -5974,6 +6012,11 @@ static void handle_beacon(struct hostapd_data *hapd,
2035 0);
2036
2037 ap_list_process_beacon(hapd->iface, mgmt, &elems, fi);
2038+
2039+#ifdef CONFIG_APUP
2040+ if (hapd->conf->apup)
2041+ apup_process_beacon(hapd, mgmt, len, &elems);
2042+#endif // def CONFIG_APUP
2043 }
2044
2045
2046diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
2047index dd4995f3f..0e13d2940 100644
2048--- a/src/ap/ieee802_11.h
2049+++ b/src/ap/ieee802_11.h
2050@@ -108,6 +108,8 @@ int hostapd_process_ml_assoc_req_addr(struct hostapd_data *hapd,
2051 const u8 *basic_mle, size_t basic_mle_len,
2052 u8 *mld_addr);
2053 int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta);
2054+u16 hostapd_copy_supp_rates(struct hostapd_data *hapd, struct sta_info *sta,
2055+ const struct ieee802_11_elems *elems);
2056 u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta,
2057 const u8 *ht_capab);
2058 u16 copy_sta_vendor_vht(struct hostapd_data *hapd, struct sta_info *sta,
developer66e89bc2024-04-23 14:50:01 +08002059diff --git a/src/ap/ieee802_11_ht.c b/src/ap/ieee802_11_ht.c
2060index f90f1254e..7f0a00f95 100644
2061--- a/src/ap/ieee802_11_ht.c
2062+++ b/src/ap/ieee802_11_ht.c
2063@@ -82,7 +82,9 @@ u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid)
2064 u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid)
2065 {
2066 struct ieee80211_ht_operation *oper;
2067+ le32 vht_capabilities_info;
2068 u8 *pos = eid;
2069+ u8 chwidth;
2070
2071 if (!hapd->iconf->ieee80211n || hapd->conf->disable_11n ||
2072 is_6ghz_op_class(hapd->iconf->op_class))
2073@@ -103,6 +105,13 @@ u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid)
2074 oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW |
2075 HT_INFO_HT_PARAM_STA_CHNL_WIDTH;
2076
2077+ vht_capabilities_info = host_to_le32(hapd->iface->current_mode->vht_capab);
2078+ chwidth = hostapd_get_oper_chwidth(hapd->iconf);
2079+ if (vht_capabilities_info & VHT_CAP_EXTENDED_NSS_BW_SUPPORT
2080+ && ((chwidth == CHANWIDTH_160MHZ) || (chwidth == CHANWIDTH_80P80MHZ))) {
2081+ oper->operation_mode = host_to_le16(hapd->iconf->vht_oper_centr_freq_seg0_idx << 5);
2082+ }
2083+
2084 pos += sizeof(*oper);
2085
2086 return pos;
2087@@ -230,6 +239,9 @@ void hostapd_2040_coex_action(struct hostapd_data *hapd,
2088 return;
2089 }
2090
2091+ if (iface->conf->noscan || iface->conf->no_ht_coex)
2092+ return;
2093+
2094 if (len < IEEE80211_HDRLEN + 2 + sizeof(*bc_ie)) {
2095 wpa_printf(MSG_DEBUG,
2096 "Ignore too short 20/40 BSS Coexistence Management frame");
2097@@ -390,6 +402,9 @@ void ht40_intolerant_add(struct hostapd_iface *iface, struct sta_info *sta)
2098 if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G)
2099 return;
2100
2101+ if (iface->conf->noscan || iface->conf->no_ht_coex)
2102+ return;
2103+
2104 wpa_printf(MSG_INFO, "HT: Forty MHz Intolerant is set by STA " MACSTR
2105 " in Association Request", MAC2STR(sta->addr));
2106
developer66e89bc2024-04-23 14:50:01 +08002107diff --git a/src/ap/ieee802_11_vht.c b/src/ap/ieee802_11_vht.c
2108index 4dc325ce8..68880ab64 100644
2109--- a/src/ap/ieee802_11_vht.c
2110+++ b/src/ap/ieee802_11_vht.c
2111@@ -26,6 +26,7 @@ u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid, u32 nsts)
2112 struct ieee80211_vht_capabilities *cap;
2113 struct hostapd_hw_modes *mode = hapd->iface->current_mode;
2114 u8 *pos = eid;
2115+ u8 chwidth;
2116
2117 if (!mode || is_6ghz_op_class(hapd->iconf->op_class))
2118 return eid;
2119@@ -63,6 +64,17 @@ u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid, u32 nsts)
2120 host_to_le32(nsts << VHT_CAP_BEAMFORMEE_STS_OFFSET);
2121 }
2122
2123+ chwidth = hostapd_get_oper_chwidth(hapd->iconf);
2124+ if (((host_to_le32(mode->vht_capab)) & VHT_CAP_EXTENDED_NSS_BW_SUPPORT)
2125+ && ((chwidth == CHANWIDTH_160MHZ) || (chwidth == CHANWIDTH_80P80MHZ))) {
2126+ cap->vht_capabilities_info |= VHT_CAP_EXTENDED_NSS_BW_SUPPORT;
2127+ cap->vht_capabilities_info &= ~(host_to_le32(VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ));
2128+ cap->vht_capabilities_info &= ~(host_to_le32(VHT_CAP_SUPP_CHAN_WIDTH_160MHZ));
2129+ cap->vht_capabilities_info &= ~(host_to_le32(VHT_CAP_SUPP_CHAN_WIDTH_MASK));
2130+ } else {
2131+ cap->vht_capabilities_info &= ~VHT_CAP_EXTENDED_NSS_BW_SUPPORT_MASK;
2132+ }
2133+
2134 /* Supported MCS set comes from hw */
2135 os_memcpy(&cap->vht_supported_mcs_set, mode->vht_mcs_set, 8);
2136
2137@@ -75,6 +87,7 @@ u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid, u32 nsts)
2138 u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid)
2139 {
2140 struct ieee80211_vht_operation *oper;
2141+ le32 vht_capabilities_info;
2142 u8 *pos = eid;
2143 enum oper_chan_width oper_chwidth =
2144 hostapd_get_oper_chwidth(hapd->iconf);
2145@@ -110,6 +123,7 @@ u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid)
2146 oper->vht_op_info_chan_center_freq_seg1_idx = seg1;
2147
2148 oper->vht_op_info_chwidth = oper_chwidth;
2149+ vht_capabilities_info = host_to_le32(hapd->iface->current_mode->vht_capab);
2150 if (oper_chwidth == CONF_OPER_CHWIDTH_160MHZ) {
2151 /*
2152 * Convert 160 MHz channel width to new style as interop
2153@@ -123,6 +137,9 @@ u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid)
2154 oper->vht_op_info_chan_center_freq_seg0_idx -= 8;
2155 else
2156 oper->vht_op_info_chan_center_freq_seg0_idx += 8;
2157+
2158+ if (vht_capabilities_info & VHT_CAP_EXTENDED_NSS_BW_SUPPORT)
2159+ oper->vht_op_info_chan_center_freq_seg1_idx = 0;
2160 } else if (oper_chwidth == CONF_OPER_CHWIDTH_80P80MHZ) {
2161 /*
2162 * Convert 80+80 MHz channel width to new style as interop
2163diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
developer05f3b2b2024-08-19 19:17:34 +08002164index f4103ac9a..7b5b45a2b 100644
developer66e89bc2024-04-23 14:50:01 +08002165--- a/src/ap/ieee802_1x.c
2166+++ b/src/ap/ieee802_1x.c
2167@@ -600,6 +600,10 @@ int add_common_radius_attr(struct hostapd_data *hapd,
2168 struct hostapd_radius_attr *attr;
2169 int len;
2170
2171+ if (hapd->conf->dynamic_own_ip_addr)
2172+ radius_client_get_local_addr(hapd->radius,
2173+ &hapd->conf->own_ip_addr);
2174+
2175 if (!hostapd_config_get_radius_attr(req_attr,
2176 RADIUS_ATTR_NAS_IP_ADDRESS) &&
2177 hapd->conf->own_ip_addr.af == AF_INET &&
developer05f3b2b2024-08-19 19:17:34 +08002178@@ -2848,6 +2852,7 @@ static const char * bool_txt(bool val)
developer66e89bc2024-04-23 14:50:01 +08002179 return val ? "TRUE" : "FALSE";
2180 }
2181
2182+#ifdef CONFIG_CTRL_IFACE_MIB
2183
2184 int ieee802_1x_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen)
2185 {
developer05f3b2b2024-08-19 19:17:34 +08002186@@ -3034,6 +3039,7 @@ int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
developer66e89bc2024-04-23 14:50:01 +08002187 return len;
2188 }
2189
2190+#endif
2191
2192 #ifdef CONFIG_HS20
2193 static void ieee802_1x_wnm_notif_send(void *eloop_ctx, void *timeout_ctx)
developer66e89bc2024-04-23 14:50:01 +08002194diff --git a/src/ap/rrm.c b/src/ap/rrm.c
developer05f3b2b2024-08-19 19:17:34 +08002195index fbcddf3f9..b024499ac 100644
developer66e89bc2024-04-23 14:50:01 +08002196--- a/src/ap/rrm.c
2197+++ b/src/ap/rrm.c
2198@@ -89,6 +89,9 @@ static void hostapd_handle_beacon_report(struct hostapd_data *hapd,
2199 return;
2200 wpa_msg(hapd->msg_ctx, MSG_INFO, BEACON_RESP_RX MACSTR " %u %02x %s",
2201 MAC2STR(addr), token, rep_mode, report);
2202+ if (len < sizeof(struct rrm_measurement_beacon_report))
2203+ return;
2204+ hostapd_ubus_notify_beacon_report(hapd, addr, token, rep_mode, (struct rrm_measurement_beacon_report*) pos, len);
2205 }
2206
2207
2208@@ -269,6 +272,8 @@ static void hostapd_send_nei_report_resp(struct hostapd_data *hapd,
2209 }
2210 }
2211
2212+ hapd->openwrt_stats.rrm.neighbor_report_tx++;
2213+
2214 hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
2215 wpabuf_head(buf), wpabuf_len(buf));
2216 wpabuf_free(buf);
developer05f3b2b2024-08-19 19:17:34 +08002217@@ -397,15 +402,20 @@ void hostapd_handle_radio_measurement(struct hostapd_data *hapd,
developer66e89bc2024-04-23 14:50:01 +08002218 mgmt->u.action.u.rrm.action, MAC2STR(mgmt->sa));
2219
2220 switch (mgmt->u.action.u.rrm.action) {
2221+ case WLAN_RRM_LINK_MEASUREMENT_REPORT:
2222+ hostapd_ubus_handle_link_measurement(hapd, buf, len);
2223+ break;
2224 case WLAN_RRM_RADIO_MEASUREMENT_REPORT:
2225 hostapd_handle_radio_msmt_report(hapd, buf, len);
2226 break;
developer05f3b2b2024-08-19 19:17:34 +08002227 case WLAN_RRM_NEIGHBOR_REPORT_REQUEST:
2228 hostapd_handle_nei_report_req(hapd, buf, len);
2229 break;
2230+ /*
2231 case WLAN_RRM_LINK_MEASUREMENT_REPORT:
2232 hostapd_handle_link_mesr_report(hapd, buf, len);
2233 break;
2234+ */
2235 default:
2236 wpa_printf(MSG_DEBUG, "RRM action %u is not supported",
2237 mgmt->u.action.u.rrm.action);
developer66e89bc2024-04-23 14:50:01 +08002238diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
developer05f3b2b2024-08-19 19:17:34 +08002239index 13613dbab..51978f45f 100644
developer66e89bc2024-04-23 14:50:01 +08002240--- a/src/ap/sta_info.c
2241+++ b/src/ap/sta_info.c
developer05f3b2b2024-08-19 19:17:34 +08002242@@ -542,6 +542,7 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
developer66e89bc2024-04-23 14:50:01 +08002243 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2244 HOSTAPD_LEVEL_INFO, "deauthenticated due to "
2245 "local deauth request");
2246+ hostapd_ubus_notify(hapd, "local-deauth", sta->addr);
2247 ap_free_sta(hapd, sta);
2248 return;
2249 }
developer05f3b2b2024-08-19 19:17:34 +08002250@@ -699,6 +700,7 @@ skip_poll:
developer66e89bc2024-04-23 14:50:01 +08002251 mlme_deauthenticate_indication(
2252 hapd, sta,
2253 WLAN_REASON_PREV_AUTH_NOT_VALID);
2254+ hostapd_ubus_notify(hapd, "inactive-deauth", sta->addr);
2255 ap_free_sta(hapd, sta);
2256 break;
2257 }
developer05f3b2b2024-08-19 19:17:34 +08002258@@ -1485,9 +1487,6 @@ bool ap_sta_set_authorized_flag(struct hostapd_data *hapd, struct sta_info *sta,
developer66e89bc2024-04-23 14:50:01 +08002259 mld_assoc_link_id = -2;
2260 }
2261 #endif /* CONFIG_IEEE80211BE */
2262- if (mld_assoc_link_id != -2)
2263- hostapd_prune_associations(hapd, sta->addr,
2264- mld_assoc_link_id);
2265 sta->flags |= WLAN_STA_AUTHORIZED;
2266 } else {
2267 sta->flags &= ~WLAN_STA_AUTHORIZED;
developer05f3b2b2024-08-19 19:17:34 +08002268@@ -1524,15 +1523,28 @@ void ap_sta_set_authorized_event(struct hostapd_data *hapd,
developer66e89bc2024-04-23 14:50:01 +08002269 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(sta->addr));
2270
2271 if (authorized) {
2272+ static const char * const auth_algs[] = {
2273+ [WLAN_AUTH_OPEN] = "open",
2274+ [WLAN_AUTH_SHARED_KEY] = "shared",
2275+ [WLAN_AUTH_FT] = "ft",
2276+ [WLAN_AUTH_SAE] = "sae",
2277+ [WLAN_AUTH_FILS_SK] = "fils-sk",
2278+ [WLAN_AUTH_FILS_SK_PFS] = "fils-sk-pfs",
2279+ [WLAN_AUTH_FILS_PK] = "fils-pk",
2280+ [WLAN_AUTH_PASN] = "pasn",
2281+ };
2282+ const char *auth_alg = NULL;
2283 const u8 *dpp_pkhash;
2284 const char *keyid;
2285 char dpp_pkhash_buf[100];
2286 char keyid_buf[100];
2287 char ip_addr[100];
2288+ char alg_buf[100];
2289
2290 dpp_pkhash_buf[0] = '\0';
2291 keyid_buf[0] = '\0';
2292 ip_addr[0] = '\0';
2293+ alg_buf[0] = '\0';
2294 #ifdef CONFIG_P2P
2295 if (wpa_auth_get_ip_addr(sta->wpa_sm, ip_addr_buf) == 0) {
2296 os_snprintf(ip_addr, sizeof(ip_addr),
developer05f3b2b2024-08-19 19:17:34 +08002297@@ -1543,6 +1555,13 @@ void ap_sta_set_authorized_event(struct hostapd_data *hapd,
developer66e89bc2024-04-23 14:50:01 +08002298 }
2299 #endif /* CONFIG_P2P */
2300
2301+ if (sta->auth_alg < ARRAY_SIZE(auth_algs))
2302+ auth_alg = auth_algs[sta->auth_alg];
2303+
2304+ if (auth_alg)
2305+ os_snprintf(alg_buf, sizeof(alg_buf),
2306+ " auth_alg=%s", auth_alg);
2307+
2308 keyid = ap_sta_wpa_get_keyid(hapd, sta);
2309 if (keyid) {
2310 os_snprintf(keyid_buf, sizeof(keyid_buf),
developer05f3b2b2024-08-19 19:17:34 +08002311@@ -1561,17 +1580,19 @@ void ap_sta_set_authorized_event(struct hostapd_data *hapd,
developer66e89bc2024-04-23 14:50:01 +08002312 dpp_pkhash, SHA256_MAC_LEN);
2313 }
2314
2315- wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s%s%s",
2316- buf, ip_addr, keyid_buf, dpp_pkhash_buf);
2317+ hostapd_ubus_notify_authorized(hapd, sta, auth_alg);
2318+ wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s%s%s%s",
2319+ buf, ip_addr, keyid_buf, dpp_pkhash_buf, alg_buf);
2320
2321 if (hapd->msg_ctx_parent &&
2322 hapd->msg_ctx_parent != hapd->msg_ctx)
2323 wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO,
2324- AP_STA_CONNECTED "%s%s%s%s",
2325+ AP_STA_CONNECTED "%s%s%s%s%s",
2326 buf, ip_addr, keyid_buf,
2327- dpp_pkhash_buf);
2328+ dpp_pkhash_buf, alg_buf);
2329 } else {
2330 wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED "%s", buf);
2331+ hostapd_ubus_notify(hapd, "disassoc", sta->addr);
2332
2333 if (hapd->msg_ctx_parent &&
2334 hapd->msg_ctx_parent != hapd->msg_ctx)
2335diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
developer05f3b2b2024-08-19 19:17:34 +08002336index 84629358c..d03d18b48 100644
developer66e89bc2024-04-23 14:50:01 +08002337--- a/src/ap/sta_info.h
2338+++ b/src/ap/sta_info.h
2339@@ -17,7 +17,6 @@
2340 #include "common/sae.h"
2341 #include "crypto/sha384.h"
2342 #include "pasn/pasn_common.h"
2343-#include "hostapd.h"
2344
2345 /* STA flags */
2346 #define WLAN_STA_AUTH BIT(0)
developer05f3b2b2024-08-19 19:17:34 +08002347@@ -49,10 +48,6 @@
2348 #define WLAN_STA_PENDING_DEAUTH_CB BIT(30)
2349 #define WLAN_STA_NONERP BIT(31)
2350
2351-/* Maximum number of supported rates (from both Supported Rates and Extended
2352- * Supported Rates IEs). */
2353-#define WLAN_SUPP_RATES_MAX 32
2354-
2355 struct hostapd_data;
2356
2357 struct mbo_non_pref_chan_info {
2358@@ -321,6 +316,7 @@ struct sta_info {
developer66e89bc2024-04-23 14:50:01 +08002359 #endif /* CONFIG_TESTING_OPTIONS */
2360 #ifdef CONFIG_AIRTIME_POLICY
2361 unsigned int airtime_weight;
2362+ unsigned int dyn_airtime_weight;
2363 struct os_reltime backlogged_until;
2364 #endif /* CONFIG_AIRTIME_POLICY */
2365
developer05f3b2b2024-08-19 19:17:34 +08002366@@ -421,16 +417,6 @@ int ap_sta_re_add(struct hostapd_data *hapd, struct sta_info *sta);
developer66e89bc2024-04-23 14:50:01 +08002367
2368 void ap_free_sta_pasn(struct hostapd_data *hapd, struct sta_info *sta);
2369
2370-static inline bool ap_sta_is_mld(struct hostapd_data *hapd,
2371- struct sta_info *sta)
2372-{
2373-#ifdef CONFIG_IEEE80211BE
2374- return hapd->conf->mld_ap && sta && sta->mld_info.mld_sta;
2375-#else /* CONFIG_IEEE80211BE */
2376- return false;
2377-#endif /* CONFIG_IEEE80211BE */
2378-}
2379-
2380 static inline void ap_sta_set_mld(struct sta_info *sta, bool mld)
2381 {
2382 #ifdef CONFIG_IEEE80211BE
developer05f3b2b2024-08-19 19:17:34 +08002383diff --git a/src/ap/ubus.c b/src/ap/ubus.c
2384index 8689494bc..f21516fc3 100644
2385--- a/src/ap/ubus.c
2386+++ b/src/ap/ubus.c
2387@@ -2004,3 +2004,18 @@ int hostapd_ubus_notify_bss_transition_query(
2388 return ureq.resp;
2389 #endif
2390 }
2391+
2392+#ifdef CONFIG_APUP
2393+void hostapd_ubus_notify_apup_newpeer(
2394+ struct hostapd_data *hapd, const u8 *addr, const char *ifname)
2395+{
2396+ if (!hapd->ubus.obj.has_subscribers)
2397+ return;
2398+
2399+ blob_buf_init(&b, 0);
2400+ blobmsg_add_macaddr(&b, "address", addr);
2401+ blobmsg_add_string(&b, "ifname", ifname);
2402+
2403+ ubus_notify(ctx, &hapd->ubus.obj, "apup-newpeer", b.head, -1);
2404+}
2405+#endif // def CONFIG_APUP
2406diff --git a/src/ap/ubus.h b/src/ap/ubus.h
2407index 22767d67e..1c65e4dcb 100644
2408--- a/src/ap/ubus.h
2409+++ b/src/ap/ubus.h
2410@@ -71,6 +71,11 @@ int hostapd_ubus_notify_bss_transition_query(
2411 void hostapd_ubus_notify_authorized(struct hostapd_data *hapd, struct sta_info *sta,
2412 const char *auth_alg);
2413
2414+#ifdef CONFIG_APUP
2415+void hostapd_ubus_notify_apup_newpeer(
2416+ struct hostapd_data *hapd, const u8 *addr, const char *ifname);
2417+#endif // def CONFIG_APUP
2418+
2419 #else
2420
2421 struct hostapd_ubus_bss {};
2422diff --git a/src/ap/ucode.c b/src/ap/ucode.c
2423index 68fb45088..3468615fd 100644
2424--- a/src/ap/ucode.c
2425+++ b/src/ap/ucode.c
2426@@ -815,3 +815,20 @@ void hostapd_ucode_free_bss(struct hostapd_data *hapd)
2427 ucv_put(wpa_ucode_call(2));
2428 ucv_gc(vm);
2429 }
2430+
2431+#ifdef CONFIG_APUP
2432+void hostapd_ucode_apup_newpeer(struct hostapd_data *hapd, const char *ifname)
2433+{
2434+ uc_value_t *val;
2435+
2436+ if (wpa_ucode_call_prepare("apup_newpeer"))
2437+ return;
2438+
2439+ val = hostapd_ucode_bss_get_uval(hapd);
2440+ uc_value_push(ucv_get(ucv_string_new(hapd->conf->iface))); // BSS ifname
2441+ uc_value_push(ucv_get(val));
2442+ uc_value_push(ucv_get(ucv_string_new(ifname))); // APuP peer ifname
2443+ ucv_put(wpa_ucode_call(2));
2444+ ucv_gc(vm);
2445+}
2446+#endif // def CONFIG_APUP
2447diff --git a/src/ap/ucode.h b/src/ap/ucode.h
2448index d00b78716..c9bdde651 100644
2449--- a/src/ap/ucode.h
2450+++ b/src/ap/ucode.h
2451@@ -27,6 +27,10 @@ void hostapd_ucode_add_bss(struct hostapd_data *hapd);
2452 void hostapd_ucode_free_bss(struct hostapd_data *hapd);
2453 void hostapd_ucode_reload_bss(struct hostapd_data *hapd);
2454
2455+#ifdef CONFIG_APUP
2456+void hostapd_ucode_apup_newpeer(struct hostapd_data *hapd, const char *ifname);
2457+#endif // def CONFIG_APUP
2458+
2459 #else
2460
2461 static inline int hostapd_ucode_init(struct hapd_interfaces *ifaces)
developer66e89bc2024-04-23 14:50:01 +08002462diff --git a/src/ap/vlan_full.c b/src/ap/vlan_full.c
2463index 19aa3c649..053d6338e 100644
2464--- a/src/ap/vlan_full.c
2465+++ b/src/ap/vlan_full.c
2466@@ -475,6 +475,9 @@ void vlan_newlink(const char *ifname, struct hostapd_data *hapd)
2467 if (!vlan)
2468 return;
2469
2470+ if (hapd->conf->ssid.vlan_no_bridge)
2471+ goto out;
2472+
2473 vlan->configured = 1;
2474
2475 notempty = vlan->vlan_desc.notempty;
2476@@ -506,6 +509,7 @@ void vlan_newlink(const char *ifname, struct hostapd_data *hapd)
2477 ifname, br_name, tagged[i], hapd);
2478 }
2479
2480+out:
2481 ifconfig_up(ifname);
2482 }
2483
2484diff --git a/src/ap/vlan_init.c b/src/ap/vlan_init.c
2485index 53eacfb45..b69f3de41 100644
2486--- a/src/ap/vlan_init.c
2487+++ b/src/ap/vlan_init.c
2488@@ -22,6 +22,7 @@
2489 static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
2490 int existsok)
2491 {
2492+ bool vlan_exists = iface_exists(vlan->ifname);
2493 int ret;
2494 #ifdef CONFIG_WEP
2495 int i;
2496@@ -36,7 +37,7 @@ static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
2497 }
2498 #endif /* CONFIG_WEP */
2499
2500- if (!iface_exists(vlan->ifname))
2501+ if (!vlan_exists)
2502 ret = hostapd_vlan_if_add(hapd, vlan->ifname);
2503 else if (!existsok)
2504 return -1;
2505@@ -51,6 +52,9 @@ static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
2506 if (hapd->wpa_auth)
2507 ret = wpa_auth_ensure_group(hapd->wpa_auth, vlan->vlan_id);
2508
2509+ if (!ret && !vlan_exists)
2510+ hostapd_ubus_add_vlan(hapd, vlan);
2511+
2512 if (ret == 0)
2513 return ret;
2514
2515@@ -77,6 +81,8 @@ int vlan_if_remove(struct hostapd_data *hapd, struct hostapd_vlan *vlan)
2516 "WPA deinitialization for VLAN %d failed (%d)",
2517 vlan->vlan_id, ret);
2518
2519+ hostapd_ubus_remove_vlan(hapd, vlan);
2520+
2521 return hostapd_vlan_if_remove(hapd, vlan->ifname);
2522 }
2523
2524diff --git a/src/ap/wnm_ap.c b/src/ap/wnm_ap.c
2525index af8cccaef..d259200c9 100644
2526--- a/src/ap/wnm_ap.c
2527+++ b/src/ap/wnm_ap.c
2528@@ -410,6 +410,7 @@ static int ieee802_11_send_bss_trans_mgmt_request(struct hostapd_data *hapd,
2529 mgmt->u.action.u.bss_tm_req.validity_interval = 1;
2530 pos = mgmt->u.action.u.bss_tm_req.variable;
2531
2532+ hapd->openwrt_stats.wnm.bss_transition_request_tx++;
2533 wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Request to "
2534 MACSTR " dialog_token=%u req_mode=0x%x disassoc_timer=%u "
2535 "validity_interval=%u",
2536@@ -478,7 +479,8 @@ static void ieee802_11_rx_bss_trans_mgmt_query(struct hostapd_data *hapd,
2537 MAC2STR(addr), reason, hex ? " neighbor=" : "", hex);
2538 os_free(hex);
2539
2540- ieee802_11_send_bss_trans_mgmt_request(hapd, addr, dialog_token);
2541+ if (!hostapd_ubus_notify_bss_transition_query(hapd, addr, dialog_token, reason, pos, end - pos))
2542+ ieee802_11_send_bss_trans_mgmt_request(hapd, addr, dialog_token);
2543 }
2544
2545
2546@@ -500,7 +502,7 @@ static void ieee802_11_rx_bss_trans_mgmt_resp(struct hostapd_data *hapd,
2547 size_t len)
2548 {
2549 u8 dialog_token, status_code, bss_termination_delay;
2550- const u8 *pos, *end;
2551+ const u8 *pos, *end, *target_bssid = NULL;
2552 int enabled = hapd->conf->bss_transition;
2553 struct sta_info *sta;
2554
2555@@ -547,6 +549,7 @@ static void ieee802_11_rx_bss_trans_mgmt_resp(struct hostapd_data *hapd,
2556 wpa_printf(MSG_DEBUG, "WNM: not enough room for Target BSSID field");
2557 return;
2558 }
2559+ target_bssid = pos;
2560 sta->agreed_to_steer = 1;
2561 eloop_cancel_timeout(ap_sta_reset_steer_flag_timer, hapd, sta);
2562 eloop_register_timeout(2, 0, ap_sta_reset_steer_flag_timer,
2563@@ -566,6 +569,10 @@ static void ieee802_11_rx_bss_trans_mgmt_resp(struct hostapd_data *hapd,
2564 MAC2STR(addr), status_code, bss_termination_delay);
2565 }
2566
2567+ hostapd_ubus_notify_bss_transition_response(hapd, sta->addr, dialog_token,
2568+ status_code, bss_termination_delay,
2569+ target_bssid, pos, end - pos);
2570+
2571 wpa_hexdump(MSG_DEBUG, "WNM: BSS Transition Candidate List Entries",
2572 pos, end - pos);
2573 }
2574@@ -814,10 +821,12 @@ int ieee802_11_rx_wnm_action_ap(struct hostapd_data *hapd,
2575 plen);
2576 return 0;
2577 case WNM_BSS_TRANS_MGMT_QUERY:
2578+ hapd->openwrt_stats.wnm.bss_transition_query_rx++;
2579 ieee802_11_rx_bss_trans_mgmt_query(hapd, mgmt->sa, payload,
2580 plen);
2581 return 0;
2582 case WNM_BSS_TRANS_MGMT_RESP:
2583+ hapd->openwrt_stats.wnm.bss_transition_response_rx++;
2584 ieee802_11_rx_bss_trans_mgmt_resp(hapd, mgmt->sa, payload,
2585 plen);
2586 return 0;
2587@@ -865,6 +874,7 @@ int wnm_send_disassoc_imminent(struct hostapd_data *hapd,
2588
2589 pos = mgmt->u.action.u.bss_tm_req.variable;
2590
2591+ hapd->openwrt_stats.wnm.bss_transition_request_tx++;
2592 wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Request frame to indicate imminent disassociation (disassoc_timer=%d) to "
2593 MACSTR, disassoc_timer, MAC2STR(sta->addr));
2594 if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0, NULL, 0, 0) < 0) {
2595@@ -947,6 +957,7 @@ int wnm_send_ess_disassoc_imminent(struct hostapd_data *hapd,
2596 return -1;
2597 }
2598
2599+ hapd->openwrt_stats.wnm.bss_transition_request_tx++;
2600 if (disassoc_timer) {
2601 /* send disassociation frame after time-out */
2602 set_disassoc_timer(hapd, sta, disassoc_timer);
2603@@ -1028,6 +1039,7 @@ int wnm_send_bss_tm_req(struct hostapd_data *hapd, struct sta_info *sta,
2604 }
2605 os_free(buf);
2606
2607+ hapd->openwrt_stats.wnm.bss_transition_request_tx++;
2608 if (disassoc_timer) {
2609 #ifdef CONFIG_IEEE80211BE
2610 if (ap_sta_is_mld(hapd, sta)) {
2611diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
developer05f3b2b2024-08-19 19:17:34 +08002612index 93f157d62..3a1d288dd 100644
developer66e89bc2024-04-23 14:50:01 +08002613--- a/src/ap/wpa_auth.c
2614+++ b/src/ap/wpa_auth.c
developer05f3b2b2024-08-19 19:17:34 +08002615@@ -6095,6 +6095,7 @@ static const char * wpa_bool_txt(int val)
developer66e89bc2024-04-23 14:50:01 +08002616 return val ? "TRUE" : "FALSE";
2617 }
2618
2619+#ifdef CONFIG_CTRL_IFACE_MIB
2620
2621 #define RSN_SUITE "%02x-%02x-%02x-%d"
2622 #define RSN_SUITE_ARG(s) \
developer05f3b2b2024-08-19 19:17:34 +08002623@@ -6247,7 +6248,7 @@ int wpa_get_mib_sta(struct wpa_state_machine *sm, char *buf, size_t buflen)
developer66e89bc2024-04-23 14:50:01 +08002624
2625 return len;
2626 }
2627-
2628+#endif
2629
2630 void wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth)
2631 {
2632diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
developer05f3b2b2024-08-19 19:17:34 +08002633index 13685b7c2..eaded9434 100644
developer66e89bc2024-04-23 14:50:01 +08002634--- a/src/ap/wpa_auth_glue.c
2635+++ b/src/ap/wpa_auth_glue.c
developer05f3b2b2024-08-19 19:17:34 +08002636@@ -328,6 +328,7 @@ static void hostapd_wpa_auth_psk_failure_report(void *ctx, const u8 *addr)
developer66e89bc2024-04-23 14:50:01 +08002637 struct hostapd_data *hapd = ctx;
2638 wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_POSSIBLE_PSK_MISMATCH MACSTR,
2639 MAC2STR(addr));
2640+ hostapd_ubus_notify(hapd, "key-mismatch", addr);
2641 }
2642
2643
developer05f3b2b2024-08-19 19:17:34 +08002644@@ -1811,8 +1812,12 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
developer66e89bc2024-04-23 14:50:01 +08002645 wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt)) {
2646 const char *ft_iface;
2647
2648- ft_iface = hapd->conf->bridge[0] ? hapd->conf->bridge :
2649- hapd->conf->iface;
2650+ if (hapd->conf->ft_iface[0])
2651+ ft_iface = hapd->conf->ft_iface;
2652+ else if (hapd->conf->bridge[0])
2653+ ft_iface = hapd->conf->bridge;
2654+ else
2655+ ft_iface = hapd->conf->iface;
2656 hapd->l2 = l2_packet_init(ft_iface, NULL, ETH_P_RRB,
2657 hostapd_rrb_receive, hapd, 1);
2658 if (!hapd->l2) {
2659diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c
2660index 82d4d5fdd..dfc5c3ecb 100644
2661--- a/src/ap/wps_hostapd.c
2662+++ b/src/ap/wps_hostapd.c
2663@@ -394,9 +394,8 @@ static int hapd_wps_reconfig_in_memory(struct hostapd_data *hapd,
2664 bss->wpa_pairwise |= WPA_CIPHER_GCMP;
2665 else
2666 bss->wpa_pairwise |= WPA_CIPHER_CCMP;
2667- }
2668 #ifndef CONFIG_NO_TKIP
2669- if (cred->encr_type & WPS_ENCR_TKIP)
2670+ } else if (cred->encr_type & WPS_ENCR_TKIP)
2671 bss->wpa_pairwise |= WPA_CIPHER_TKIP;
2672 #endif /* CONFIG_NO_TKIP */
2673 bss->rsn_pairwise = bss->wpa_pairwise;
2674@@ -1181,8 +1180,7 @@ int hostapd_init_wps(struct hostapd_data *hapd,
2675 WPA_CIPHER_GCMP_256)) {
2676 wps->encr_types |= WPS_ENCR_AES;
2677 wps->encr_types_rsn |= WPS_ENCR_AES;
2678- }
2679- if (conf->rsn_pairwise & WPA_CIPHER_TKIP) {
2680+ } else if (conf->rsn_pairwise & WPA_CIPHER_TKIP) {
2681 #ifdef CONFIG_NO_TKIP
2682 wpa_printf(MSG_INFO, "WPS: TKIP not supported");
2683 goto fail;
2684diff --git a/src/ap/x_snoop.c b/src/ap/x_snoop.c
2685index 029f4de23..4c20f137f 100644
2686--- a/src/ap/x_snoop.c
2687+++ b/src/ap/x_snoop.c
2688@@ -33,28 +33,31 @@ int x_snoop_init(struct hostapd_data *hapd)
2689
2690 hapd->x_snoop_initialized = true;
2691
2692- if (hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_HAIRPIN_MODE,
2693+ if (!conf->snoop_iface[0] &&
2694+ hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_HAIRPIN_MODE,
2695 1)) {
2696 wpa_printf(MSG_DEBUG,
2697 "x_snoop: Failed to enable hairpin_mode on the bridge port");
2698 return -1;
2699 }
2700
2701- if (hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_PROXYARP, 1)) {
2702+ if (!conf->snoop_iface[0] &&
2703+ hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_PROXYARP, 1)) {
2704 wpa_printf(MSG_DEBUG,
2705 "x_snoop: Failed to enable proxyarp on the bridge port");
2706 return -1;
2707 }
2708
2709 if (hostapd_drv_br_set_net_param(hapd, DRV_BR_NET_PARAM_GARP_ACCEPT,
2710- 1)) {
2711+ conf->snoop_iface[0] ? conf->snoop_iface : NULL, 1)) {
2712 wpa_printf(MSG_DEBUG,
2713 "x_snoop: Failed to enable accepting gratuitous ARP on the bridge");
2714 return -1;
2715 }
2716
2717 #ifdef CONFIG_IPV6
2718- if (hostapd_drv_br_set_net_param(hapd, DRV_BR_MULTICAST_SNOOPING, 1)) {
2719+ if (!conf->snoop_iface[0] &&
2720+ hostapd_drv_br_set_net_param(hapd, DRV_BR_MULTICAST_SNOOPING, NULL, 1)) {
2721 wpa_printf(MSG_DEBUG,
2722 "x_snoop: Failed to enable multicast snooping on the bridge");
2723 return -1;
2724@@ -73,8 +76,12 @@ x_snoop_get_l2_packet(struct hostapd_data *hapd,
2725 {
2726 struct hostapd_bss_config *conf = hapd->conf;
2727 struct l2_packet_data *l2;
2728+ const char *ifname = conf->bridge;
2729+
2730+ if (conf->snoop_iface[0])
2731+ ifname = conf->snoop_iface;
2732
2733- l2 = l2_packet_init(conf->bridge, NULL, ETH_P_ALL, handler, hapd, 1);
2734+ l2 = l2_packet_init(ifname, NULL, ETH_P_ALL, handler, hapd, 1);
2735 if (l2 == NULL) {
2736 wpa_printf(MSG_DEBUG,
2737 "x_snoop: Failed to initialize L2 packet processing %s",
2738@@ -127,9 +134,12 @@ void x_snoop_mcast_to_ucast_convert_send(struct hostapd_data *hapd,
2739
2740 void x_snoop_deinit(struct hostapd_data *hapd)
2741 {
2742+ struct hostapd_bss_config *conf = hapd->conf;
2743+
2744 if (!hapd->x_snoop_initialized)
2745 return;
2746- hostapd_drv_br_set_net_param(hapd, DRV_BR_NET_PARAM_GARP_ACCEPT, 0);
2747+ hostapd_drv_br_set_net_param(hapd, DRV_BR_NET_PARAM_GARP_ACCEPT,
2748+ conf->snoop_iface[0] ? conf->snoop_iface : NULL, 0);
2749 hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_PROXYARP, 0);
2750 hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_HAIRPIN_MODE, 0);
2751 hapd->x_snoop_initialized = false;
developer05f3b2b2024-08-19 19:17:34 +08002752diff --git a/src/common/defs.h b/src/common/defs.h
2753index 8cca094e8..151b69170 100644
2754--- a/src/common/defs.h
2755+++ b/src/common/defs.h
2756@@ -63,6 +63,10 @@
2757 WPA_KEY_MGMT_FT_FILS_SHA256 | \
2758 WPA_KEY_MGMT_FT_FILS_SHA384)
2759
2760+/* Maximum number of supported rates (from both Supported Rates and Extended
2761+ * Supported Rates IEs). */
2762+#define WLAN_SUPP_RATES_MAX 32
2763+
2764 static inline int wpa_key_mgmt_wpa_ieee8021x(int akm)
2765 {
2766 return !!(akm & (WPA_KEY_MGMT_IEEE8021X |
developer66e89bc2024-04-23 14:50:01 +08002767diff --git a/src/common/dpp_crypto.c b/src/common/dpp_crypto.c
2768index f17f95a2c..39d39f429 100644
2769--- a/src/common/dpp_crypto.c
2770+++ b/src/common/dpp_crypto.c
2771@@ -269,6 +269,12 @@ int dpp_get_pubkey_hash(struct crypto_ec_key *key, u8 *hash)
2772
2773 struct crypto_ec_key * dpp_gen_keypair(const struct dpp_curve_params *curve)
2774 {
2775+ if (curve == NULL) {
2776+ wpa_printf(MSG_DEBUG,
2777+ "DPP: %s curve must be initialized", __func__);
2778+ return NULL;
2779+ }
2780+
2781 struct crypto_ec_key *key;
2782
2783 wpa_printf(MSG_DEBUG, "DPP: Generating a keypair");
2784@@ -1582,7 +1588,9 @@ dpp_pkex_derive_Qr(const struct dpp_curve_params *curve, const u8 *mac_resp,
2785 Pr = crypto_ec_key_get_public_key(Pr_key);
2786 Qr = crypto_ec_point_init(ec);
2787 hash_bn = crypto_bignum_init_set(hash, curve->hash_len);
2788- if (!Pr || !Qr || !hash_bn || crypto_ec_point_mul(ec, Pr, hash_bn, Qr))
2789+ if (!Pr || !Qr || !hash_bn ||
2790+ crypto_bignum_mod(hash_bn, crypto_ec_get_prime(ec), hash_bn) ||
2791+ crypto_ec_point_mul(ec, Pr, hash_bn, Qr))
2792 goto fail;
2793
2794 if (crypto_ec_point_is_at_infinity(ec, Qr)) {
2795diff --git a/src/common/hw_features_common.c b/src/common/hw_features_common.c
2796index 2c47bf812..8bd6e994d 100644
2797--- a/src/common/hw_features_common.c
2798+++ b/src/common/hw_features_common.c
2799@@ -898,6 +898,7 @@ int ieee80211ac_cap_check(u32 hw, u32 conf)
2800 VHT_CAP_CHECK(VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB);
2801 VHT_CAP_CHECK(VHT_CAP_RX_ANTENNA_PATTERN);
2802 VHT_CAP_CHECK(VHT_CAP_TX_ANTENNA_PATTERN);
2803+ VHT_CAP_CHECK(VHT_CAP_EXTENDED_NSS_BW_SUPPORT);
2804
2805 #undef VHT_CAP_CHECK
2806 #undef VHT_CAP_CHECK_MAX
2807diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
developer05f3b2b2024-08-19 19:17:34 +08002808index db9e90355..269b1cf97 100644
developer66e89bc2024-04-23 14:50:01 +08002809--- a/src/common/ieee802_11_defs.h
2810+++ b/src/common/ieee802_11_defs.h
developer05f3b2b2024-08-19 19:17:34 +08002811@@ -1398,6 +1398,8 @@ struct ieee80211_ampe_ie {
developer66e89bc2024-04-23 14:50:01 +08002812 #define VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB ((u32) BIT(26) | BIT(27))
2813 #define VHT_CAP_RX_ANTENNA_PATTERN ((u32) BIT(28))
2814 #define VHT_CAP_TX_ANTENNA_PATTERN ((u32) BIT(29))
2815+#define VHT_CAP_EXTENDED_NSS_BW_SUPPORT ((u32) BIT(30))
2816+#define VHT_CAP_EXTENDED_NSS_BW_SUPPORT_MASK ((u32) BIT(30) | BIT(31))
2817
2818 #define VHT_OPMODE_CHANNEL_WIDTH_MASK ((u8) BIT(0) | BIT(1))
2819 #define VHT_OPMODE_CHANNEL_RxNSS_MASK ((u8) BIT(4) | BIT(5) | \
2820diff --git a/src/common/sae.c b/src/common/sae.c
developer05f3b2b2024-08-19 19:17:34 +08002821index a65da6134..36f09e31b 100644
developer66e89bc2024-04-23 14:50:01 +08002822--- a/src/common/sae.c
2823+++ b/src/common/sae.c
2824@@ -1278,6 +1278,13 @@ void sae_deinit_pt(struct sae_pt *pt)
2825 static int sae_derive_commit_element_ecc(struct sae_data *sae,
2826 struct crypto_bignum *mask)
2827 {
2828+ if (sae->tmp->pwe_ecc == NULL) {
2829+ wpa_printf(MSG_DEBUG,
2830+ "SAE: %s sae->tmp->pwe_ecc must be initialized",
2831+ __func__);
2832+ return -1;
2833+ }
2834+
2835 /* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */
2836 if (!sae->tmp->own_commit_element_ecc) {
2837 sae->tmp->own_commit_element_ecc =
developer66e89bc2024-04-23 14:50:01 +08002838diff --git a/src/common/wpa_ctrl.c b/src/common/wpa_ctrl.c
developer05f3b2b2024-08-19 19:17:34 +08002839index d0c174c05..ba659fe0f 100644
developer66e89bc2024-04-23 14:50:01 +08002840--- a/src/common/wpa_ctrl.c
2841+++ b/src/common/wpa_ctrl.c
developer05f3b2b2024-08-19 19:17:34 +08002842@@ -142,7 +142,7 @@ try_again:
developer66e89bc2024-04-23 14:50:01 +08002843 return NULL;
2844 }
2845 tries++;
2846-#ifdef ANDROID
2847+
2848 /* Set client socket file permissions so that bind() creates the client
2849 * socket with these permissions and there is no need to try to change
2850 * them with chmod() after bind() which would have potential issues with
developer05f3b2b2024-08-19 19:17:34 +08002851@@ -154,7 +154,7 @@ try_again:
developer66e89bc2024-04-23 14:50:01 +08002852 * operations to allow the response to go through. Those are using the
2853 * no-deference-symlinks version to avoid races. */
2854 fchmod(ctrl->s, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
2855-#endif /* ANDROID */
2856+
2857 if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
2858 sizeof(ctrl->local)) < 0) {
2859 if (errno == EADDRINUSE && tries < 2) {
developer05f3b2b2024-08-19 19:17:34 +08002860@@ -172,7 +172,11 @@ try_again:
developer66e89bc2024-04-23 14:50:01 +08002861 return NULL;
2862 }
2863
2864-#ifdef ANDROID
2865+#ifndef ANDROID
2866+ /* Set group even if we do not have privileges to change owner */
2867+ lchown(ctrl->local.sun_path, -1, 101);
2868+ lchown(ctrl->local.sun_path, 101, 101);
2869+#else
2870 /* Set group even if we do not have privileges to change owner */
2871 lchown(ctrl->local.sun_path, -1, AID_WIFI);
2872 lchown(ctrl->local.sun_path, AID_SYSTEM, AID_WIFI);
2873diff --git a/src/crypto/Makefile b/src/crypto/Makefile
2874index ce0997091..96bac9476 100644
2875--- a/src/crypto/Makefile
2876+++ b/src/crypto/Makefile
2877@@ -1,10 +1,121 @@
2878-CFLAGS += -DCONFIG_CRYPTO_INTERNAL
2879-CFLAGS += -DCONFIG_TLS_INTERNAL_CLIENT
2880-CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER
2881 #CFLAGS += -DALL_DH_GROUPS
2882 CFLAGS += -DCONFIG_SHA256
2883 CFLAGS += -DCONFIG_SHA384
2884+CFLAGS += -DCONFIG_HMAC_SHA256_KDF
2885 CFLAGS += -DCONFIG_HMAC_SHA384_KDF
2886+
2887+# crypto_module_tests.c
2888+CFLAGS += -DCONFIG_MODULE_TESTS
2889+CFLAGS += -DCONFIG_DPP
2890+#CFLAGS += -DCONFIG_DPP2
2891+#CFLAGS += -DCONFIG_DPP3
2892+CFLAGS += -DCONFIG_ECC
2893+CFLAGS += -DCONFIG_MESH
2894+CFLAGS += -DEAP_PSK
2895+CFLAGS += -DEAP_FAST
2896+
2897+ifeq ($(CONFIG_TLS),mbedtls)
2898+
2899+# (enable features for 'cd tests; make run-tests CONFIG_TLS=mbedtls')
2900+CFLAGS += -DCRYPTO_RSA_OAEP_SHA256
2901+CFLAGS += -DCONFIG_DES
2902+CFLAGS += -DEAP_IKEV2
2903+CFLAGS += -DEAP_MSCHAPv2
2904+CFLAGS += -DEAP_SIM
2905+
2906+LIB_OBJS = tls_mbedtls.o crypto_mbedtls.o
2907+LIB_OBJS+= \
2908+ aes-eax.o \
2909+ aes-siv.o \
2910+ dh_groups.o \
2911+ milenage.o \
2912+ ms_funcs.o
2913+
2914+else
2915+ifeq ($(CONFIG_TLS),openssl)
2916+
2917+# (enable features for 'cd tests; make run-tests CONFIG_TLS=openssl')
2918+ifndef CONFIG_TLS_DEFAULT_CIPHERS
2919+CONFIG_TLS_DEFAULT_CIPHERS = "DEFAULT:!EXP:!LOW"
2920+endif
2921+CFLAGS += -DTLS_DEFAULT_CIPHERS=\"$(CONFIG_TLS_DEFAULT_CIPHERS)\"
2922+CFLAGS += -DCRYPTO_RSA_OAEP_SHA256
2923+CFLAGS += -DEAP_TLS_OPENSSL
2924+
2925+LIB_OBJS = tls_openssl.o fips_prf_openssl.o crypto_openssl.o
2926+LIB_OBJS+= \
2927+ aes-ctr.o \
2928+ aes-eax.o \
2929+ aes-encblock.o \
2930+ aes-siv.o \
2931+ dh_groups.o \
2932+ milenage.o \
2933+ ms_funcs.o \
2934+ sha1-prf.o \
2935+ sha1-tlsprf.o \
2936+ sha1-tprf.o \
2937+ sha256-kdf.o \
2938+ sha256-prf.o \
2939+ sha256-tlsprf.o
2940+
2941+else
2942+ifeq ($(CONFIG_TLS),wolfssl)
2943+
2944+# (wolfssl libraries must be built with ./configure --enable-wpas)
2945+# (enable features for 'cd tests; make run-tests CONFIG_TLS=wolfssl')
2946+CFLAGS += -DWOLFSSL_DER_LOAD
2947+CFLAGS += -DCONFIG_DES
2948+
2949+LIB_OBJS = tls_wolfssl.o fips_prf_wolfssl.o crypto_wolfssl.o
2950+LIB_OBJS+= \
2951+ aes-ctr.o \
2952+ aes-eax.o \
2953+ aes-encblock.o \
2954+ aes-siv.o \
2955+ dh_groups.o \
2956+ milenage.o \
2957+ ms_funcs.o \
2958+ sha1-prf.o \
2959+ sha1-tlsprf.o \
2960+ sha1-tprf.o \
2961+ sha256-kdf.o \
2962+ sha256-prf.o \
2963+ sha256-tlsprf.o
2964+
2965+else
2966+ifeq ($(CONFIG_TLS),gnutls)
2967+
2968+# (enable features for 'cd tests; make run-tests CONFIG_TLS=gnutls')
2969+LIB_OBJS = tls_gnutls.o crypto_gnutls.o
2970+LIB_OBJS+= \
2971+ aes-cbc.o \
2972+ aes-ctr.o \
2973+ aes-eax.o \
2974+ aes-encblock.o \
2975+ aes-omac1.o \
2976+ aes-siv.o \
2977+ aes-unwrap.o \
2978+ aes-wrap.o \
2979+ dh_group5.o \
2980+ dh_groups.o \
2981+ milenage.o \
2982+ ms_funcs.o \
2983+ rc4.o \
2984+ sha1-pbkdf2.o \
2985+ sha1-prf.o \
2986+ fips_prf_internal.o \
2987+ sha1-internal.o \
2988+ sha1-tlsprf.o \
2989+ sha1-tprf.o \
2990+ sha256-kdf.o \
2991+ sha256-prf.o \
2992+ sha256-tlsprf.o
2993+
2994+else
2995+
2996+CFLAGS += -DCONFIG_CRYPTO_INTERNAL
2997+CFLAGS += -DCONFIG_TLS_INTERNAL_CLIENT
2998+CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER
2999 CFLAGS += -DCONFIG_INTERNAL_SHA384
3000
3001 LIB_OBJS= \
3002@@ -13,7 +124,6 @@ LIB_OBJS= \
3003 aes-ctr.o \
3004 aes-eax.o \
3005 aes-encblock.o \
3006- aes-gcm.o \
3007 aes-internal.o \
3008 aes-internal-dec.o \
3009 aes-internal-enc.o \
3010@@ -37,6 +147,7 @@ LIB_OBJS= \
3011 sha1-tlsprf.o \
3012 sha1-tprf.o \
3013 sha256.o \
3014+ sha256-kdf.o \
3015 sha256-prf.o \
3016 sha256-tlsprf.o \
3017 sha256-internal.o \
3018@@ -53,6 +164,16 @@ LIB_OBJS += crypto_internal-modexp.o
3019 LIB_OBJS += crypto_internal-rsa.o
3020 LIB_OBJS += tls_internal.o
3021 LIB_OBJS += fips_prf_internal.o
3022+
3023+endif
3024+endif
3025+endif
3026+endif
3027+
3028+
3029+# (used by wlantest/{bip,gcmp,rx_mgmt}.c and tests/test-aes.c)
3030+LIB_OBJS += aes-gcm.o
3031+
3032 ifndef TEST_FUZZ
3033 LIB_OBJS += random.o
3034 endif
3035diff --git a/src/crypto/crypto_mbedtls.c b/src/crypto/crypto_mbedtls.c
3036new file mode 100644
3037index 000000000..7a91c965f
3038--- /dev/null
3039+++ b/src/crypto/crypto_mbedtls.c
3040@@ -0,0 +1,4228 @@
3041+/*
3042+ * crypto wrapper functions for mbed TLS
3043+ *
3044+ * SPDX-FileCopyrightText: 2022 Glenn Strauss <gstrauss@gluelogic.com>
3045+ * SPDX-License-Identifier: BSD-3-Clause
3046+ */
3047+
3048+#include "utils/includes.h"
3049+#include "utils/common.h"
3050+
3051+#include <mbedtls/version.h>
3052+#include <mbedtls/entropy.h>
3053+#include <mbedtls/ctr_drbg.h>
3054+#include <mbedtls/platform_util.h> /* mbedtls_platform_zeroize() */
3055+#include <mbedtls/asn1.h>
3056+#include <mbedtls/asn1write.h>
3057+#include <mbedtls/aes.h>
3058+#include <mbedtls/md.h>
3059+#include <mbedtls/md5.h>
3060+#include <mbedtls/sha1.h>
3061+#include <mbedtls/sha256.h>
3062+#include <mbedtls/sha512.h>
3063+
3064+#ifndef MBEDTLS_PRIVATE
3065+#define MBEDTLS_PRIVATE(x) x
3066+#endif
3067+
3068+/* hostapd/wpa_supplicant provides forced_memzero(),
3069+ * but prefer mbedtls_platform_zeroize() */
3070+#define forced_memzero(ptr,sz) mbedtls_platform_zeroize(ptr,sz)
3071+
3072+#ifndef __has_attribute
3073+#define __has_attribute(x) 0
3074+#endif
3075+
3076+#ifndef __GNUC_PREREQ
3077+#define __GNUC_PREREQ(maj,min) 0
3078+#endif
3079+
3080+#ifndef __attribute_cold__
3081+#if __has_attribute(cold) \
3082+ || __GNUC_PREREQ(4,3)
3083+#define __attribute_cold__ __attribute__((__cold__))
3084+#else
3085+#define __attribute_cold__
3086+#endif
3087+#endif
3088+
3089+#ifndef __attribute_noinline__
3090+#if __has_attribute(noinline) \
3091+ || __GNUC_PREREQ(3,1)
3092+#define __attribute_noinline__ __attribute__((__noinline__))
3093+#else
3094+#define __attribute_noinline__
3095+#endif
3096+#endif
3097+
3098+#include "crypto.h"
3099+#include "aes_wrap.h"
3100+#include "aes.h"
3101+#include "md5.h"
3102+#include "sha1.h"
3103+#include "sha256.h"
3104+#include "sha384.h"
3105+#include "sha512.h"
3106+
3107+
3108+/*
3109+ * selective code inclusion based on preprocessor defines
3110+ *
3111+ * future: additional code could be wrapped with preprocessor checks if
3112+ * wpa_supplicant/Makefile and hostap/Makefile were more consistent with
3113+ * setting preprocessor defines for named groups of functionality
3114+ */
3115+
3116+#if defined(CONFIG_FIPS)
3117+#undef MBEDTLS_MD4_C /* omit md4_vector() */
3118+#undef MBEDTLS_MD5_C /* omit md5_vector() hmac_md5_vector() hmac_md5() */
3119+#undef MBEDTLS_DES_C /* omit des_encrypt() */
3120+#undef MBEDTLS_NIST_KW_C /* omit aes_wrap() aes_unwrap() */
3121+#define CRYPTO_MBEDTLS_CONFIG_FIPS
3122+#endif
3123+
3124+#if !defined(CONFIG_FIPS)
3125+#if defined(EAP_PWD) \
3126+ || defined(EAP_LEAP) || defined(EAP_LEAP_DYNAMIC) \
3127+ || defined(EAP_TTLS) || defined(EAP_TTLS_DYNAMIC) \
3128+ || defined(EAP_MSCHAPv2) || defined(EAP_MSCHAPv2_DYNAMIC) \
3129+ || defined(EAP_SERVER_MSCHAPV2)
3130+#ifndef MBEDTLS_MD4_C /* (MD4 not in mbedtls 3.x) */
3131+#include "md4-internal.c"/* pull in hostap local implementation */
3132+#endif /* md4_vector() */
3133+#else
3134+#undef MBEDTLS_MD4_C /* omit md4_vector() */
3135+#endif
3136+#endif
3137+
3138+#if !defined(CONFIG_NO_RC4) && !defined(CONFIG_NO_WPA)
3139+#ifndef MBEDTLS_ARC4_C /* (RC4 not in mbedtls 3.x) */
3140+#include "rc4.c" /* pull in hostap local implementation */
3141+#endif /* rc4_skip() */
3142+#else
3143+#undef MBEDTLS_ARC4_C /* omit rc4_skip() */
3144+#endif
3145+
3146+#if defined(CONFIG_MACSEC) \
3147+ || defined(CONFIG_NO_RADIUS) \
3148+ || defined(CONFIG_IEEE80211R) \
3149+ || defined(EAP_SERVER_FAST) \
3150+ || defined(EAP_SERVER_TEAP) \
3151+ || !defined(CONFIG_NO_WPA)
3152+ /* aes_wrap() aes_unwrap() */
3153+#else
3154+#undef MBEDTLS_NIST_KW_C /* omit aes_wrap() aes_unwrap() */
3155+#endif
3156+
3157+#if !defined(CONFIG_SHA256)
3158+#undef MBEDTLS_SHA256_C
3159+#endif
3160+
3161+#if !defined(CONFIG_SHA384) && !defined(CONFIG_SHA512)
3162+#undef MBEDTLS_SHA512_C
3163+#endif
3164+
3165+#if defined(CONFIG_HMAC_SHA256_KDF)
3166+#define CRYPTO_MBEDTLS_HMAC_KDF_SHA256
3167+#endif
3168+#if defined(CONFIG_HMAC_SHA384_KDF)
3169+#define CRYPTO_MBEDTLS_HMAC_KDF_SHA384
3170+#endif
3171+#if defined(CONFIG_HMAC_SHA512_KDF)
3172+#define CRYPTO_MBEDTLS_HMAC_KDF_SHA512
3173+#endif
3174+
3175+#if defined(EAP_SIM) || defined(EAP_SIM_DYNAMIC) || defined(EAP_SERVER_SIM) \
3176+ || defined(EAP_AKA) || defined(EAP_AKA_DYNAMIC) || defined(EAP_SERVER_AKA)
3177+/* EAP_SIM=y EAP_AKA=y */
3178+#define CRYPTO_MBEDTLS_FIPS186_2_PRF
3179+#endif
3180+
3181+#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) \
3182+ || defined(EAP_TEAP) || defined(EAP_TEAP_DYNAMIC) || defined(EAP_SERVER_FAST)
3183+#define CRYPTO_MBEDTLS_SHA1_T_PRF
3184+#endif
3185+
3186+#if defined(CONFIG_DES)
3187+#define CRYPTO_MBEDTLS_DES_ENCRYPT
3188+#endif /* des_encrypt() */
3189+
3190+#if !defined(CONFIG_NO_PBKDF2)
3191+#define CRYPTO_MBEDTLS_PBKDF2_SHA1
3192+#endif /* pbkdf2_sha1() */
3193+
3194+#if defined(EAP_IKEV2) \
3195+ || defined(EAP_IKEV2_DYNAMIC) \
3196+ || defined(EAP_SERVER_IKEV2) /* CONFIG_EAP_IKEV2=y */
3197+#define CRYPTO_MBEDTLS_CRYPTO_CIPHER
3198+#endif /* crypto_cipher_*() */
3199+
3200+#if defined(EAP_PWD) || defined(EAP_SERVER_PWD) /* CONFIG_EAP_PWD=y */
3201+#define CRYPTO_MBEDTLS_CRYPTO_HASH
3202+#endif /* crypto_hash_*() */
3203+
3204+#if defined(EAP_PWD) || defined(EAP_SERVER_PWD) /* CONFIG_EAP_PWD=y */ \
3205+ || defined(CONFIG_SAE) /* CONFIG_SAE=y */
3206+#define CRYPTO_MBEDTLS_CRYPTO_BIGNUM
3207+#endif /* crypto_bignum_*() */
3208+
3209+#if defined(EAP_PWD) /* CONFIG_EAP_PWD=y */ \
3210+ || defined(EAP_EKE) /* CONFIG_EAP_EKE=y */ \
3211+ || defined(EAP_EKE_DYNAMIC) /* CONFIG_EAP_EKE=y */ \
3212+ || defined(EAP_SERVER_EKE) /* CONFIG_EAP_EKE=y */ \
3213+ || defined(EAP_IKEV2) /* CONFIG_EAP_IKEV2y */ \
3214+ || defined(EAP_IKEV2_DYNAMIC)/* CONFIG_EAP_IKEV2=y */ \
3215+ || defined(EAP_SERVER_IKEV2) /* CONFIG_EAP_IKEV2=y */ \
3216+ || defined(CONFIG_SAE) /* CONFIG_SAE=y */ \
3217+ || defined(CONFIG_WPS) /* CONFIG_WPS=y */
3218+#define CRYPTO_MBEDTLS_CRYPTO_DH
3219+#if defined(CONFIG_WPS_NFC)
3220+#define CRYPTO_MBEDTLS_DH5_INIT_FIXED
3221+#endif /* dh5_init_fixed() */
3222+#endif /* crypto_dh_*() */
3223+
3224+#if !defined(CONFIG_NO_WPA) /* CONFIG_NO_WPA= */
3225+#define CRYPTO_MBEDTLS_CRYPTO_ECDH
3226+#endif /* crypto_ecdh_*() */
3227+
3228+#if defined(CONFIG_ECC)
3229+#define CRYPTO_MBEDTLS_CRYPTO_BIGNUM
3230+#define CRYPTO_MBEDTLS_CRYPTO_EC
3231+#endif /* crypto_ec_*() crypto_ec_key_*() */
3232+
3233+#if defined(CONFIG_DPP) /* CONFIG_DPP=y */
3234+#define CRYPTO_MBEDTLS_CRYPTO_EC_DPP /* extra for DPP */
3235+#define CRYPTO_MBEDTLS_CRYPTO_CSR
3236+#endif /* crypto_csr_*() */
3237+
3238+#if defined(CONFIG_DPP3) /* CONFIG_DPP3=y */
3239+#define CRYPTO_MBEDTLS_CRYPTO_HPKE
3240+#endif
3241+
3242+#if defined(CONFIG_DPP2) /* CONFIG_DPP2=y */
3243+#define CRYPTO_MBEDTLS_CRYPTO_PKCS7
3244+#endif /* crypto_pkcs7_*() */
3245+
3246+#if defined(EAP_SIM) || defined(EAP_SIM_DYNAMIC) || defined(EAP_SERVER_SIM) \
3247+ || defined(EAP_AKA) || defined(EAP_AKA_DYNAMIC) || defined(EAP_SERVER_AKA) \
3248+ || defined(CONFIG_AP) || defined(HOSTAPD)
3249+/* CONFIG_EAP_SIM=y CONFIG_EAP_AKA=y CONFIG_AP=y HOSTAPD */
3250+#if defined(CRYPTO_RSA_OAEP_SHA256)
3251+#define CRYPTO_MBEDTLS_CRYPTO_RSA
3252+#endif
3253+#endif /* crypto_rsa_*() */
3254+
3255+
3256+static int ctr_drbg_init_state;
3257+static mbedtls_ctr_drbg_context ctr_drbg;
3258+static mbedtls_entropy_context entropy;
3259+
3260+#ifdef CRYPTO_MBEDTLS_CRYPTO_BIGNUM
3261+#include <mbedtls/bignum.h>
3262+static mbedtls_mpi mpi_sw_A;
3263+#endif
3264+
3265+__attribute_cold__
3266+__attribute_noinline__
3267+static mbedtls_ctr_drbg_context * ctr_drbg_init(void)
3268+{
3269+ mbedtls_ctr_drbg_init(&ctr_drbg);
3270+ mbedtls_entropy_init(&entropy);
3271+ if (mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
3272+ NULL, 0)) {
3273+ wpa_printf(MSG_ERROR, "Init of random number generator failed");
3274+ /* XXX: abort? */
3275+ }
3276+ else
3277+ ctr_drbg_init_state = 1;
3278+
3279+ return &ctr_drbg;
3280+}
3281+
3282+__attribute_cold__
3283+void crypto_unload(void)
3284+{
3285+ if (ctr_drbg_init_state) {
3286+ mbedtls_ctr_drbg_free(&ctr_drbg);
3287+ mbedtls_entropy_free(&entropy);
3288+ #ifdef CRYPTO_MBEDTLS_CRYPTO_BIGNUM
3289+ mbedtls_mpi_free(&mpi_sw_A);
3290+ #endif
3291+ ctr_drbg_init_state = 0;
3292+ }
3293+}
3294+
3295+/* init ctr_drbg on first use
3296+ * crypto_global_init() and crypto_global_deinit() are not available here
3297+ * (available only when CONFIG_TLS=internal, which is not CONFIG_TLS=mbedtls) */
3298+mbedtls_ctr_drbg_context * crypto_mbedtls_ctr_drbg(void); /*(not in header)*/
3299+inline
3300+mbedtls_ctr_drbg_context * crypto_mbedtls_ctr_drbg(void)
3301+{
3302+ return ctr_drbg_init_state ? &ctr_drbg : ctr_drbg_init();
3303+}
3304+
3305+#ifdef CRYPTO_MBEDTLS_CONFIG_FIPS
3306+int crypto_get_random(void *buf, size_t len)
3307+{
3308+ return mbedtls_ctr_drbg_random(crypto_mbedtls_ctr_drbg(),buf,len) ? -1 : 0;
3309+}
3310+#endif
3311+
3312+
3313+#if 1
3314+
3315+/* tradeoff: slightly smaller code size here at cost of slight increase
3316+ * in instructions and function calls at runtime versus the expanded
3317+ * per-message-digest code that follows in #else (~0.5 kib .text larger) */
3318+
3319+__attribute_noinline__
3320+static int md_vector(size_t num_elem, const u8 *addr[], const size_t *len,
3321+ u8 *mac, mbedtls_md_type_t md_type)
3322+{
3323+ if (TEST_FAIL())
3324+ return -1;
3325+
3326+ mbedtls_md_context_t ctx;
3327+ mbedtls_md_init(&ctx);
3328+ if (mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 0) != 0){
3329+ mbedtls_md_free(&ctx);
3330+ return -1;
3331+ }
3332+ mbedtls_md_starts(&ctx);
3333+ for (size_t i = 0; i < num_elem; ++i)
3334+ mbedtls_md_update(&ctx, addr[i], len[i]);
3335+ mbedtls_md_finish(&ctx, mac);
3336+ mbedtls_md_free(&ctx);
3337+ return 0;
3338+}
3339+
3340+#ifdef MBEDTLS_SHA512_C
3341+int sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
3342+{
3343+ return md_vector(num_elem, addr, len, mac, MBEDTLS_MD_SHA512);
3344+}
3345+
3346+int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
3347+{
3348+ return md_vector(num_elem, addr, len, mac, MBEDTLS_MD_SHA384);
3349+}
3350+#endif
3351+
3352+#ifdef MBEDTLS_SHA256_C
3353+int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
3354+{
3355+ return md_vector(num_elem, addr, len, mac, MBEDTLS_MD_SHA256);
3356+}
3357+#endif
3358+
3359+#ifdef MBEDTLS_SHA1_C
3360+int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
3361+{
3362+ return md_vector(num_elem, addr, len, mac, MBEDTLS_MD_SHA1);
3363+}
3364+#endif
3365+
3366+#ifdef MBEDTLS_MD5_C
3367+int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
3368+{
3369+ return md_vector(num_elem, addr, len, mac, MBEDTLS_MD_MD5);
3370+}
3371+#endif
3372+
3373+#ifdef MBEDTLS_MD4_C
3374+#include <mbedtls/md4.h>
3375+int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
3376+{
3377+ return md_vector(num_elem, addr, len, mac, MBEDTLS_MD_MD4);
3378+}
3379+#endif
3380+
3381+#else /* expanded per-message-digest functions */
3382+
3383+#ifdef MBEDTLS_SHA512_C
3384+#include <mbedtls/sha512.h>
3385+__attribute_noinline__
3386+static int sha384_512_vector(size_t num_elem, const u8 *addr[],
3387+ const size_t *len, u8 *mac, int is384)
3388+{
3389+ if (TEST_FAIL())
3390+ return -1;
3391+
3392+ struct mbedtls_sha512_context ctx;
3393+ mbedtls_sha512_init(&ctx);
3394+ #if MBEDTLS_VERSION_MAJOR >= 3
3395+ mbedtls_sha512_starts(&ctx, is384);
3396+ for (size_t i = 0; i < num_elem; ++i)
3397+ mbedtls_sha512_update(&ctx, addr[i], len[i]);
3398+ mbedtls_sha512_finish(&ctx, mac);
3399+ #else
3400+ mbedtls_sha512_starts_ret(&ctx, is384);
3401+ for (size_t i = 0; i < num_elem; ++i)
3402+ mbedtls_sha512_update_ret(&ctx, addr[i], len[i]);
3403+ mbedtls_sha512_finish_ret(&ctx, mac);
3404+ #endif
3405+ mbedtls_sha512_free(&ctx);
3406+ return 0;
3407+}
3408+
3409+int sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
3410+{
3411+ return sha384_512_vector(num_elem, addr, len, mac, 0);
3412+}
3413+
3414+int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
3415+{
3416+ return sha384_512_vector(num_elem, addr, len, mac, 1);
3417+}
3418+#endif
3419+
3420+#ifdef MBEDTLS_SHA256_C
3421+#include <mbedtls/sha256.h>
3422+int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
3423+{
3424+ if (TEST_FAIL())
3425+ return -1;
3426+
3427+ struct mbedtls_sha256_context ctx;
3428+ mbedtls_sha256_init(&ctx);
3429+ #if MBEDTLS_VERSION_MAJOR >= 3
3430+ mbedtls_sha256_starts(&ctx, 0);
3431+ for (size_t i = 0; i < num_elem; ++i)
3432+ mbedtls_sha256_update(&ctx, addr[i], len[i]);
3433+ mbedtls_sha256_finish(&ctx, mac);
3434+ #else
3435+ mbedtls_sha256_starts_ret(&ctx, 0);
3436+ for (size_t i = 0; i < num_elem; ++i)
3437+ mbedtls_sha256_update_ret(&ctx, addr[i], len[i]);
3438+ mbedtls_sha256_finish_ret(&ctx, mac);
3439+ #endif
3440+ mbedtls_sha256_free(&ctx);
3441+ return 0;
3442+}
3443+#endif
3444+
3445+#ifdef MBEDTLS_SHA1_C
3446+#include <mbedtls/sha1.h>
3447+int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
3448+{
3449+ if (TEST_FAIL())
3450+ return -1;
3451+
3452+ struct mbedtls_sha1_context ctx;
3453+ mbedtls_sha1_init(&ctx);
3454+ #if MBEDTLS_VERSION_MAJOR >= 3
3455+ mbedtls_sha1_starts(&ctx);
3456+ for (size_t i = 0; i < num_elem; ++i)
3457+ mbedtls_sha1_update(&ctx, addr[i], len[i]);
3458+ mbedtls_sha1_finish(&ctx, mac);
3459+ #else
3460+ mbedtls_sha1_starts_ret(&ctx);
3461+ for (size_t i = 0; i < num_elem; ++i)
3462+ mbedtls_sha1_update_ret(&ctx, addr[i], len[i]);
3463+ mbedtls_sha1_finish_ret(&ctx, mac);
3464+ #endif
3465+ mbedtls_sha1_free(&ctx);
3466+ return 0;
3467+}
3468+#endif
3469+
3470+#ifdef MBEDTLS_MD5_C
3471+#include <mbedtls/md5.h>
3472+int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
3473+{
3474+ if (TEST_FAIL())
3475+ return -1;
3476+
3477+ struct mbedtls_md5_context ctx;
3478+ mbedtls_md5_init(&ctx);
3479+ #if MBEDTLS_VERSION_MAJOR >= 3
3480+ mbedtls_md5_starts(&ctx);
3481+ for (size_t i = 0; i < num_elem; ++i)
3482+ mbedtls_md5_update(&ctx, addr[i], len[i]);
3483+ mbedtls_md5_finish(&ctx, mac);
3484+ #else
3485+ mbedtls_md5_starts_ret(&ctx);
3486+ for (size_t i = 0; i < num_elem; ++i)
3487+ mbedtls_md5_update_ret(&ctx, addr[i], len[i]);
3488+ mbedtls_md5_finish_ret(&ctx, mac);
3489+ #endif
3490+ mbedtls_md5_free(&ctx);
3491+ return 0;
3492+}
3493+#endif
3494+
3495+#ifdef MBEDTLS_MD4_C
3496+#include <mbedtls/md4.h>
3497+int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
3498+{
3499+ if (TEST_FAIL())
3500+ return -1;
3501+
3502+ struct mbedtls_md4_context ctx;
3503+ mbedtls_md4_init(&ctx);
3504+ mbedtls_md4_starts_ret(&ctx);
3505+ for (size_t i = 0; i < num_elem; ++i)
3506+ mbedtls_md4_update_ret(&ctx, addr[i], len[i]);
3507+ mbedtls_md4_finish_ret(&ctx, mac);
3508+ mbedtls_md4_free(&ctx);
3509+ return 0;
3510+}
3511+#endif
3512+
3513+#endif /* expanded per-message-digest functions */
3514+
3515+
3516+__attribute_noinline__
3517+static int hmac_vector(const u8 *key, size_t key_len, size_t num_elem,
3518+ const u8 *addr[], const size_t *len, u8 *mac,
3519+ mbedtls_md_type_t md_type)
3520+{
3521+ if (TEST_FAIL())
3522+ return -1;
3523+
3524+ mbedtls_md_context_t ctx;
3525+ mbedtls_md_init(&ctx);
3526+ if (mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 1) != 0){
3527+ mbedtls_md_free(&ctx);
3528+ return -1;
3529+ }
3530+ mbedtls_md_hmac_starts(&ctx, key, key_len);
3531+ for (size_t i = 0; i < num_elem; ++i)
3532+ mbedtls_md_hmac_update(&ctx, addr[i], len[i]);
3533+ mbedtls_md_hmac_finish(&ctx, mac);
3534+ mbedtls_md_free(&ctx);
3535+ return 0;
3536+}
3537+
3538+#ifdef MBEDTLS_SHA512_C
3539+int hmac_sha512_vector(const u8 *key, size_t key_len, size_t num_elem,
3540+ const u8 *addr[], const size_t *len, u8 *mac)
3541+{
3542+ return hmac_vector(key, key_len, num_elem, addr, len, mac,
3543+ MBEDTLS_MD_SHA512);
3544+}
3545+
3546+int hmac_sha512(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
3547+ u8 *mac)
3548+{
3549+ return hmac_vector(key, key_len, 1, &data, &data_len, mac,
3550+ MBEDTLS_MD_SHA512);
3551+}
3552+
3553+int hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem,
3554+ const u8 *addr[], const size_t *len, u8 *mac)
3555+{
3556+ return hmac_vector(key, key_len, num_elem, addr, len, mac,
3557+ MBEDTLS_MD_SHA384);
3558+}
3559+
3560+int hmac_sha384(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
3561+ u8 *mac)
3562+{
3563+ return hmac_vector(key, key_len, 1, &data, &data_len, mac,
3564+ MBEDTLS_MD_SHA384);
3565+}
3566+#endif
3567+
3568+#ifdef MBEDTLS_SHA256_C
3569+int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
3570+ const u8 *addr[], const size_t *len, u8 *mac)
3571+{
3572+ return hmac_vector(key, key_len, num_elem, addr, len, mac,
3573+ MBEDTLS_MD_SHA256);
3574+}
3575+
3576+int hmac_sha256(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
3577+ u8 *mac)
3578+{
3579+ return hmac_vector(key, key_len, 1, &data, &data_len, mac,
3580+ MBEDTLS_MD_SHA256);
3581+}
3582+#endif
3583+
3584+#ifdef MBEDTLS_SHA1_C
3585+int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
3586+ const u8 *addr[], const size_t *len, u8 *mac)
3587+{
3588+ return hmac_vector(key, key_len, num_elem, addr, len, mac,
3589+ MBEDTLS_MD_SHA1);
3590+}
3591+
3592+int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
3593+ u8 *mac)
3594+{
3595+ return hmac_vector(key, key_len, 1, &data, &data_len, mac,
3596+ MBEDTLS_MD_SHA1);
3597+}
3598+#endif
3599+
3600+#ifdef MBEDTLS_MD5_C
3601+int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
3602+ const u8 *addr[], const size_t *len, u8 *mac)
3603+{
3604+ return hmac_vector(key, key_len, num_elem, addr, len, mac,
3605+ MBEDTLS_MD_MD5);
3606+}
3607+
3608+int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
3609+ u8 *mac)
3610+{
3611+ return hmac_vector(key, key_len, 1, &data, &data_len, mac,
3612+ MBEDTLS_MD_MD5);
3613+}
3614+#endif
3615+
3616+
3617+#if defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA512_C)
3618+
3619+#if defined(CRYPTO_MBEDTLS_HMAC_KDF_SHA256) \
3620+ || defined(CRYPTO_MBEDTLS_HMAC_KDF_SHA384) \
3621+ || defined(CRYPTO_MBEDTLS_HMAC_KDF_SHA512)
3622+
3623+#include <mbedtls/hkdf.h>
3624+
3625+/* sha256-kdf.c sha384-kdf.c sha512-kdf.c */
3626+
3627+/* HMAC-SHA256 KDF (RFC 5295) and HKDF-Expand(SHA256) (RFC 5869) */
3628+/* HMAC-SHA384 KDF (RFC 5295) and HKDF-Expand(SHA384) (RFC 5869) */
3629+/* HMAC-SHA512 KDF (RFC 5295) and HKDF-Expand(SHA512) (RFC 5869) */
3630+__attribute_noinline__
3631+static int hmac_kdf_expand(const u8 *prk, size_t prk_len,
3632+ const char *label, const u8 *info, size_t info_len,
3633+ u8 *okm, size_t okm_len, mbedtls_md_type_t md_type)
3634+{
3635+ if (TEST_FAIL())
3636+ return -1;
3637+
3638+ const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_type);
3639+ #ifdef MBEDTLS_HKDF_C
3640+ if (label == NULL) /* RFC 5869 HKDF-Expand when (label == NULL) */
3641+ return mbedtls_hkdf_expand(md_info, prk, prk_len, info,
3642+ info_len, okm, okm_len) ? -1 : 0;
3643+ #endif
3644+
3645+ const size_t mac_len = mbedtls_md_get_size(md_info);
3646+ /* okm_len must not exceed 255 times hash len (RFC 5869 Section 2.3) */
3647+ if (okm_len > ((mac_len << 8) - mac_len))
3648+ return -1;
3649+
3650+ mbedtls_md_context_t ctx;
3651+ mbedtls_md_init(&ctx);
3652+ if (mbedtls_md_setup(&ctx, md_info, 1) != 0) {
3653+ mbedtls_md_free(&ctx);
3654+ return -1;
3655+ }
3656+ mbedtls_md_hmac_starts(&ctx, prk, prk_len);
3657+
3658+ u8 iter = 1;
3659+ const u8 *addr[4] = { okm, (const u8 *)label, info, &iter };
3660+ size_t len[4] = { 0, label ? os_strlen(label)+1 : 0, info_len, 1 };
3661+
3662+ for (; okm_len >= mac_len; okm_len -= mac_len, ++iter) {
3663+ for (size_t i = 0; i < ARRAY_SIZE(addr); ++i)
3664+ mbedtls_md_hmac_update(&ctx, addr[i], len[i]);
3665+ mbedtls_md_hmac_finish(&ctx, okm);
3666+ mbedtls_md_hmac_reset(&ctx);
3667+ addr[0] = okm;
3668+ okm += mac_len;
3669+ len[0] = mac_len; /*(include digest in subsequent rounds)*/
3670+ }
3671+
3672+ if (okm_len) {
3673+ u8 hash[MBEDTLS_MD_MAX_SIZE];
3674+ for (size_t i = 0; i < ARRAY_SIZE(addr); ++i)
3675+ mbedtls_md_hmac_update(&ctx, addr[i], len[i]);
3676+ mbedtls_md_hmac_finish(&ctx, hash);
3677+ os_memcpy(okm, hash, okm_len);
3678+ forced_memzero(hash, mac_len);
3679+ }
3680+
3681+ mbedtls_md_free(&ctx);
3682+ return 0;
3683+}
3684+
3685+#ifdef MBEDTLS_SHA512_C
3686+#ifdef CRYPTO_MBEDTLS_HMAC_KDF_SHA512
3687+int hmac_sha512_kdf(const u8 *secret, size_t secret_len,
3688+ const char *label, const u8 *seed, size_t seed_len,
3689+ u8 *out, size_t outlen)
3690+{
3691+ return hmac_kdf_expand(secret, secret_len, label, seed, seed_len,
3692+ out, outlen, MBEDTLS_MD_SHA512);
3693+}
3694+#endif
3695+
3696+#ifdef CRYPTO_MBEDTLS_HMAC_KDF_SHA384
3697+int hmac_sha384_kdf(const u8 *secret, size_t secret_len,
3698+ const char *label, const u8 *seed, size_t seed_len,
3699+ u8 *out, size_t outlen)
3700+{
3701+ return hmac_kdf_expand(secret, secret_len, label, seed, seed_len,
3702+ out, outlen, MBEDTLS_MD_SHA384);
3703+}
3704+#endif
3705+#endif
3706+
3707+#ifdef MBEDTLS_SHA256_C
3708+#ifdef CRYPTO_MBEDTLS_HMAC_KDF_SHA256
3709+int hmac_sha256_kdf(const u8 *secret, size_t secret_len,
3710+ const char *label, const u8 *seed, size_t seed_len,
3711+ u8 *out, size_t outlen)
3712+{
3713+ return hmac_kdf_expand(secret, secret_len, label, seed, seed_len,
3714+ out, outlen, MBEDTLS_MD_SHA256);
3715+}
3716+#endif
3717+#endif
3718+
3719+#endif /* CRYPTO_MBEDTLS_HMAC_KDF_* */
3720+
3721+
3722+/* sha256-prf.c sha384-prf.c sha512-prf.c */
3723+
3724+/* hmac_prf_bits - IEEE Std 802.11ac-2013, 11.6.1.7.2 Key derivation function */
3725+__attribute_noinline__
3726+static int hmac_prf_bits(const u8 *key, size_t key_len, const char *label,
3727+ const u8 *data, size_t data_len, u8 *buf,
3728+ size_t buf_len_bits, mbedtls_md_type_t md_type)
3729+{
3730+ if (TEST_FAIL())
3731+ return -1;
3732+
3733+ mbedtls_md_context_t ctx;
3734+ mbedtls_md_init(&ctx);
3735+ const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_type);
3736+ if (mbedtls_md_setup(&ctx, md_info, 1) != 0) {
3737+ mbedtls_md_free(&ctx);
3738+ return -1;
3739+ }
3740+ mbedtls_md_hmac_starts(&ctx, key, key_len);
3741+
3742+ u16 ctr, n_le = host_to_le16(buf_len_bits);
3743+ const u8 * const addr[] = { (u8 *)&ctr,(u8 *)label,data,(u8 *)&n_le };
3744+ const size_t len[] = { 2, os_strlen(label), data_len, 2 };
3745+ const size_t mac_len = mbedtls_md_get_size(md_info);
3746+ size_t buf_len = (buf_len_bits + 7) / 8;
3747+ for (ctr = 1; buf_len >= mac_len; buf_len -= mac_len, ++ctr) {
3748+ #if __BYTE_ORDER == __BIG_ENDIAN
3749+ ctr = host_to_le16(ctr);
3750+ #endif
3751+ for (size_t i = 0; i < ARRAY_SIZE(addr); ++i)
3752+ mbedtls_md_hmac_update(&ctx, addr[i], len[i]);
3753+ mbedtls_md_hmac_finish(&ctx, buf);
3754+ mbedtls_md_hmac_reset(&ctx);
3755+ buf += mac_len;
3756+ #if __BYTE_ORDER == __BIG_ENDIAN
3757+ ctr = le_to_host16(ctr);
3758+ #endif
3759+ }
3760+
3761+ if (buf_len) {
3762+ u8 hash[MBEDTLS_MD_MAX_SIZE];
3763+ #if __BYTE_ORDER == __BIG_ENDIAN
3764+ ctr = host_to_le16(ctr);
3765+ #endif
3766+ for (size_t i = 0; i < ARRAY_SIZE(addr); ++i)
3767+ mbedtls_md_hmac_update(&ctx, addr[i], len[i]);
3768+ mbedtls_md_hmac_finish(&ctx, hash);
3769+ os_memcpy(buf, hash, buf_len);
3770+ buf += buf_len;
3771+ forced_memzero(hash, mac_len);
3772+ }
3773+
3774+ /* Mask out unused bits in last octet if it does not use all the bits */
3775+ if ((buf_len_bits &= 0x7))
3776+ buf[-1] &= (u8)(0xff << (8 - buf_len_bits));
3777+
3778+ mbedtls_md_free(&ctx);
3779+ return 0;
3780+}
3781+
3782+#ifdef MBEDTLS_SHA512_C
3783+int sha512_prf(const u8 *key, size_t key_len, const char *label,
3784+ const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
3785+{
3786+ return hmac_prf_bits(key, key_len, label, data, data_len, buf,
3787+ buf_len * 8, MBEDTLS_MD_SHA512);
3788+}
3789+
3790+int sha384_prf(const u8 *key, size_t key_len, const char *label,
3791+ const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
3792+{
3793+ return hmac_prf_bits(key, key_len, label, data, data_len, buf,
3794+ buf_len * 8, MBEDTLS_MD_SHA384);
3795+}
3796+#endif
3797+
3798+#ifdef MBEDTLS_SHA256_C
3799+int sha256_prf(const u8 *key, size_t key_len, const char *label,
3800+ const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
3801+{
3802+ return hmac_prf_bits(key, key_len, label, data, data_len, buf,
3803+ buf_len * 8, MBEDTLS_MD_SHA256);
3804+}
3805+
3806+int sha256_prf_bits(const u8 *key, size_t key_len, const char *label,
3807+ const u8 *data, size_t data_len, u8 *buf,
3808+ size_t buf_len_bits)
3809+{
3810+ return hmac_prf_bits(key, key_len, label, data, data_len, buf,
3811+ buf_len_bits, MBEDTLS_MD_SHA256);
3812+}
3813+#endif
3814+
3815+#endif /* MBEDTLS_SHA256_C || MBEDTLS_SHA512_C */
3816+
3817+
3818+#ifdef MBEDTLS_SHA1_C
3819+
3820+/* sha1-prf.c */
3821+
3822+/* sha1_prf - SHA1-based Pseudo-Random Function (PRF) (IEEE 802.11i, 8.5.1.1) */
3823+
3824+int sha1_prf(const u8 *key, size_t key_len, const char *label,
3825+ const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
3826+{
3827+ /*(note: algorithm differs from hmac_prf_bits() */
3828+ /*(note: smaller code size instead of expanding hmac_sha1_vector()
3829+ * as is done in hmac_prf_bits(); not expecting large num of loops) */
3830+ u8 counter = 0;
3831+ const u8 *addr[] = { (u8 *)label, data, &counter };
3832+ const size_t len[] = { os_strlen(label)+1, data_len, 1 };
3833+
3834+ for (; buf_len >= SHA1_MAC_LEN; buf_len -= SHA1_MAC_LEN, ++counter) {
3835+ if (hmac_sha1_vector(key, key_len, 3, addr, len, buf))
3836+ return -1;
3837+ buf += SHA1_MAC_LEN;
3838+ }
3839+
3840+ if (buf_len) {
3841+ u8 hash[SHA1_MAC_LEN];
3842+ if (hmac_sha1_vector(key, key_len, 3, addr, len, hash))
3843+ return -1;
3844+ os_memcpy(buf, hash, buf_len);
3845+ forced_memzero(hash, sizeof(hash));
3846+ }
3847+
3848+ return 0;
3849+}
3850+
3851+#ifdef CRYPTO_MBEDTLS_SHA1_T_PRF
3852+
3853+/* sha1-tprf.c */
3854+
3855+/* sha1_t_prf - EAP-FAST Pseudo-Random Function (T-PRF) (RFC 4851,Section 5.5)*/
3856+
3857+int sha1_t_prf(const u8 *key, size_t key_len, const char *label,
3858+ const u8 *seed, size_t seed_len, u8 *buf, size_t buf_len)
3859+{
3860+ /*(note: algorithm differs from hmac_prf_bits() and hmac_kdf() above)*/
3861+ /*(note: smaller code size instead of expanding hmac_sha1_vector()
3862+ * as is done in hmac_prf_bits(); not expecting large num of loops) */
3863+ u8 ctr;
3864+ u16 olen = host_to_be16(buf_len);
3865+ const u8 *addr[] = { buf, (u8 *)label, seed, (u8 *)&olen, &ctr };
3866+ size_t len[] = { 0, os_strlen(label)+1, seed_len, 2, 1 };
3867+
3868+ for (ctr = 1; buf_len >= SHA1_MAC_LEN; buf_len -= SHA1_MAC_LEN, ++ctr) {
3869+ if (hmac_sha1_vector(key, key_len, 5, addr, len, buf))
3870+ return -1;
3871+ addr[0] = buf;
3872+ buf += SHA1_MAC_LEN;
3873+ len[0] = SHA1_MAC_LEN; /*(include digest in subsequent rounds)*/
3874+ }
3875+
3876+ if (buf_len) {
3877+ u8 hash[SHA1_MAC_LEN];
3878+ if (hmac_sha1_vector(key, key_len, 5, addr, len, hash))
3879+ return -1;
3880+ os_memcpy(buf, hash, buf_len);
3881+ forced_memzero(hash, sizeof(hash));
3882+ }
3883+
3884+ return 0;
3885+}
3886+
3887+#endif /* CRYPTO_MBEDTLS_SHA1_T_PRF */
3888+
3889+#ifdef CRYPTO_MBEDTLS_FIPS186_2_PRF
3890+
3891+/* fips_prf_internal.c sha1-internal.c */
3892+
3893+/* used only by src/eap_common/eap_sim_common.c:eap_sim_prf()
3894+ * for eap_sim_derive_keys() and eap_sim_derive_keys_reauth()
3895+ * where xlen is 160 */
3896+
3897+int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
3898+{
3899+ /* FIPS 186-2 + change notice 1 */
3900+
3901+ mbedtls_sha1_context ctx;
3902+ u8 * const xkey = ctx.MBEDTLS_PRIVATE(buffer);
3903+ u32 * const xstate = ctx.MBEDTLS_PRIVATE(state);
3904+ const u32 xstate_init[] =
3905+ { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 };
3906+
3907+ mbedtls_sha1_init(&ctx);
3908+ os_memcpy(xkey, seed, seed_len < 64 ? seed_len : 64);
3909+
3910+ /* note: does not fill extra bytes if (xlen % 20) (SHA1_MAC_LEN) */
3911+ for (; xlen >= 20; xlen -= 20) {
3912+ /* XSEED_j = 0 */
3913+ /* XVAL = (XKEY + XSEED_j) mod 2^b */
3914+
3915+ /* w_i = G(t, XVAL) */
3916+ os_memcpy(xstate, xstate_init, sizeof(xstate_init));
3917+ mbedtls_internal_sha1_process(&ctx, xkey);
3918+
3919+ #if __BYTE_ORDER == __LITTLE_ENDIAN
3920+ xstate[0] = host_to_be32(xstate[0]);
3921+ xstate[1] = host_to_be32(xstate[1]);
3922+ xstate[2] = host_to_be32(xstate[2]);
3923+ xstate[3] = host_to_be32(xstate[3]);
3924+ xstate[4] = host_to_be32(xstate[4]);
3925+ #endif
3926+ os_memcpy(x, xstate, 20);
3927+ if (xlen == 20) /*(done; skip prep for next loop)*/
3928+ break;
3929+
3930+ /* XKEY = (1 + XKEY + w_i) mod 2^b */
3931+ for (u32 carry = 1, k = 20; k-- > 0; carry >>= 8)
3932+ xkey[k] = (carry += xkey[k] + x[k]) & 0xff;
3933+ x += 20;
3934+ /* x_j = w_0|w_1 (each pair of iterations through loop)*/
3935+ }
3936+
3937+ mbedtls_sha1_free(&ctx);
3938+ return 0;
3939+}
3940+
3941+#endif /* CRYPTO_MBEDTLS_FIPS186_2_PRF */
3942+
3943+#endif /* MBEDTLS_SHA1_C */
3944+
3945+
3946+#ifdef CRYPTO_MBEDTLS_DES_ENCRYPT
3947+#ifdef MBEDTLS_DES_C
3948+#include <mbedtls/des.h>
3949+int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
3950+{
3951+ u8 pkey[8], next, tmp;
3952+ int i;
3953+
3954+ /* Add parity bits to the key */
3955+ next = 0;
3956+ for (i = 0; i < 7; i++) {
3957+ tmp = key[i];
3958+ pkey[i] = (tmp >> i) | next | 1;
3959+ next = tmp << (7 - i);
3960+ }
3961+ pkey[i] = next | 1;
3962+
3963+ mbedtls_des_context des;
3964+ mbedtls_des_init(&des);
3965+ int ret = mbedtls_des_setkey_enc(&des, pkey)
3966+ || mbedtls_des_crypt_ecb(&des, clear, cypher) ? -1 : 0;
3967+ mbedtls_des_free(&des);
3968+ return ret;
3969+}
3970+#else
3971+#include "des-internal.c"/* pull in hostap local implementation */
3972+#endif
3973+#endif
3974+
3975+
3976+#ifdef CRYPTO_MBEDTLS_PBKDF2_SHA1
3977+/* sha1-pbkdf2.c */
3978+#include <mbedtls/pkcs5.h>
3979+int pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len,
3980+ int iterations, u8 *buf, size_t buflen)
3981+{
3982+ #if MBEDTLS_VERSION_NUMBER >= 0x03020200 /* mbedtls 3.2.2 */
3983+ return mbedtls_pkcs5_pbkdf2_hmac_ext(MBEDTLS_MD_SHA1,
3984+ (const u8 *)passphrase, os_strlen(passphrase),
3985+ ssid, ssid_len, iterations, 32, buf) ? -1 : 0;
3986+ #else
3987+ const mbedtls_md_info_t *md_info;
3988+ md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
3989+ if (md_info == NULL)
3990+ return -1;
3991+ mbedtls_md_context_t ctx;
3992+ mbedtls_md_init(&ctx);
3993+ int ret = mbedtls_md_setup(&ctx, md_info, 1)
3994+ || mbedtls_pkcs5_pbkdf2_hmac(&ctx,
3995+ (const u8 *)passphrase, os_strlen(passphrase),
3996+ ssid, ssid_len, iterations, 32, buf) ? -1 : 0;
3997+ mbedtls_md_free(&ctx);
3998+ return ret;
3999+ #endif
4000+}
4001+#endif
4002+
4003+
4004+/*#include "aes.h"*/ /* prototypes also included in "crypto.h" */
4005+
4006+static void *aes_crypt_init_mode(const u8 *key, size_t len, int mode)
4007+{
4008+ if (TEST_FAIL())
4009+ return NULL;
4010+
4011+ mbedtls_aes_context *aes = os_malloc(sizeof(*aes));
4012+ if (!aes)
4013+ return NULL;
4014+
4015+ mbedtls_aes_init(aes);
4016+ if ((mode == MBEDTLS_AES_ENCRYPT
4017+ ? mbedtls_aes_setkey_enc(aes, key, len * 8)
4018+ : mbedtls_aes_setkey_dec(aes, key, len * 8)) == 0)
4019+ return aes;
4020+
4021+ mbedtls_aes_free(aes);
4022+ os_free(aes);
4023+ return NULL;
4024+}
4025+
4026+void *aes_encrypt_init(const u8 *key, size_t len)
4027+{
4028+ return aes_crypt_init_mode(key, len, MBEDTLS_AES_ENCRYPT);
4029+}
4030+
4031+int aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
4032+{
4033+ return mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, plain, crypt);
4034+}
4035+
4036+void aes_encrypt_deinit(void *ctx)
4037+{
4038+ mbedtls_aes_free(ctx);
4039+ os_free(ctx);
4040+}
4041+
4042+void *aes_decrypt_init(const u8 *key, size_t len)
4043+{
4044+ return aes_crypt_init_mode(key, len, MBEDTLS_AES_DECRYPT);
4045+}
4046+
4047+int aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
4048+{
4049+ return mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_DECRYPT, crypt, plain);
4050+}
4051+
4052+void aes_decrypt_deinit(void *ctx)
4053+{
4054+ mbedtls_aes_free(ctx);
4055+ os_free(ctx);
4056+}
4057+
4058+
4059+#include "aes_wrap.h"
4060+
4061+
4062+#ifdef MBEDTLS_NIST_KW_C
4063+
4064+#include <mbedtls/nist_kw.h>
4065+
4066+/* aes-wrap.c */
4067+int aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain, u8 *cipher)
4068+{
4069+ if (TEST_FAIL())
4070+ return -1;
4071+
4072+ mbedtls_nist_kw_context ctx;
4073+ mbedtls_nist_kw_init(&ctx);
4074+ size_t olen;
4075+ int ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
4076+ kek, kek_len*8, 1)
4077+ || mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KW, plain, n*8,
4078+ cipher, &olen, (n+1)*8) ? -1 : 0;
4079+ mbedtls_nist_kw_free(&ctx);
4080+ return ret;
4081+}
4082+
4083+/* aes-unwrap.c */
4084+int aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher, u8 *plain)
4085+{
4086+ if (TEST_FAIL())
4087+ return -1;
4088+
4089+ mbedtls_nist_kw_context ctx;
4090+ mbedtls_nist_kw_init(&ctx);
4091+ size_t olen;
4092+ int ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
4093+ kek, kek_len*8, 0)
4094+ || mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KW, cipher,
4095+ (n+1)*8, plain, &olen, n*8) ? -1 : 0;
4096+ mbedtls_nist_kw_free(&ctx);
4097+ return ret;
4098+}
4099+
4100+#else
4101+
4102+#ifndef CRYPTO_MBEDTLS_CONFIG_FIPS
4103+#include "aes-wrap.c" /* pull in hostap local implementation */
4104+#include "aes-unwrap.c" /* pull in hostap local implementation */
4105+#endif
4106+
4107+#endif /* MBEDTLS_NIST_KW_C */
4108+
4109+
4110+#ifdef MBEDTLS_CMAC_C
4111+
4112+/* aes-omac1.c */
4113+
4114+#include <mbedtls/cmac.h>
4115+
4116+int omac1_aes_vector(
4117+ const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[],
4118+ const size_t *len, u8 *mac)
4119+{
4120+ if (TEST_FAIL())
4121+ return -1;
4122+
4123+ mbedtls_cipher_type_t cipher_type;
4124+ switch (key_len) {
4125+ case 16: cipher_type = MBEDTLS_CIPHER_AES_128_ECB; break;
4126+ case 24: cipher_type = MBEDTLS_CIPHER_AES_192_ECB; break;
4127+ case 32: cipher_type = MBEDTLS_CIPHER_AES_256_ECB; break;
4128+ default: return -1;
4129+ }
4130+ const mbedtls_cipher_info_t *cipher_info;
4131+ cipher_info = mbedtls_cipher_info_from_type(cipher_type);
4132+ if (cipher_info == NULL)
4133+ return -1;
4134+
4135+ mbedtls_cipher_context_t ctx;
4136+ mbedtls_cipher_init(&ctx);
4137+ int ret = -1;
4138+ if (mbedtls_cipher_setup(&ctx, cipher_info) == 0
4139+ && mbedtls_cipher_cmac_starts(&ctx, key, key_len*8) == 0) {
4140+ ret = 0;
4141+ for (size_t i = 0; i < num_elem && ret == 0; ++i)
4142+ ret = mbedtls_cipher_cmac_update(&ctx, addr[i], len[i]);
4143+ }
4144+ if (ret == 0)
4145+ ret = mbedtls_cipher_cmac_finish(&ctx, mac);
4146+ mbedtls_cipher_free(&ctx);
4147+ return ret ? -1 : 0;
4148+}
4149+
4150+int omac1_aes_128_vector(const u8 *key, size_t num_elem,
4151+ const u8 *addr[], const size_t *len,
4152+ u8 *mac)
4153+{
4154+ return omac1_aes_vector(key, 16, num_elem, addr, len, mac);
4155+}
4156+
4157+int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
4158+{
4159+ return omac1_aes_vector(key, 16, 1, &data, &data_len, mac);
4160+}
4161+
4162+int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
4163+{
4164+ return omac1_aes_vector(key, 32, 1, &data, &data_len, mac);
4165+}
4166+
4167+#else
4168+
4169+#include "aes-omac1.c" /* pull in hostap local implementation */
4170+
4171+#ifndef MBEDTLS_AES_BLOCK_SIZE
4172+#define MBEDTLS_AES_BLOCK_SIZE 16
4173+#endif
4174+
4175+#endif /* MBEDTLS_CMAC_C */
4176+
4177+
4178+/* These interfaces can be inefficient when used in loops, as the overhead of
4179+ * initialization each call is large for each block input (e.g. 16 bytes) */
4180+
4181+
4182+/* aes-encblock.c */
4183+int aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out)
4184+{
4185+ if (TEST_FAIL())
4186+ return -1;
4187+
4188+ mbedtls_aes_context aes;
4189+ mbedtls_aes_init(&aes);
4190+ int ret = mbedtls_aes_setkey_enc(&aes, key, 128)
4191+ || mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_ENCRYPT, in, out)
4192+ ? -1
4193+ : 0;
4194+ mbedtls_aes_free(&aes);
4195+ return ret;
4196+}
4197+
4198+
4199+/* aes-ctr.c */
4200+int aes_ctr_encrypt(const u8 *key, size_t key_len, const u8 *nonce,
4201+ u8 *data, size_t data_len)
4202+{
4203+ if (TEST_FAIL())
4204+ return -1;
4205+
4206+ unsigned char counter[MBEDTLS_AES_BLOCK_SIZE];
4207+ unsigned char stream_block[MBEDTLS_AES_BLOCK_SIZE];
4208+ os_memcpy(counter, nonce, MBEDTLS_AES_BLOCK_SIZE);/*(must be writable)*/
4209+
4210+ mbedtls_aes_context ctx;
4211+ mbedtls_aes_init(&ctx);
4212+ size_t nc_off = 0;
4213+ int ret = mbedtls_aes_setkey_enc(&ctx, key, key_len*8)
4214+ || mbedtls_aes_crypt_ctr(&ctx, data_len, &nc_off,
4215+ counter, stream_block,
4216+ data, data) ? -1 : 0;
4217+ forced_memzero(stream_block, sizeof(stream_block));
4218+ mbedtls_aes_free(&ctx);
4219+ return ret;
4220+}
4221+
4222+int aes_128_ctr_encrypt(const u8 *key, const u8 *nonce,
4223+ u8 *data, size_t data_len)
4224+{
4225+ return aes_ctr_encrypt(key, 16, nonce, data, data_len);
4226+}
4227+
4228+
4229+/* aes-cbc.c */
4230+static int aes_128_cbc_oper(const u8 *key, const u8 *iv,
4231+ u8 *data, size_t data_len, int mode)
4232+{
4233+ unsigned char ivec[MBEDTLS_AES_BLOCK_SIZE];
4234+ os_memcpy(ivec, iv, MBEDTLS_AES_BLOCK_SIZE); /*(must be writable)*/
4235+
4236+ mbedtls_aes_context ctx;
4237+ mbedtls_aes_init(&ctx);
4238+ int ret = (mode == MBEDTLS_AES_ENCRYPT
4239+ ? mbedtls_aes_setkey_enc(&ctx, key, 128)
4240+ : mbedtls_aes_setkey_dec(&ctx, key, 128))
4241+ || mbedtls_aes_crypt_cbc(&ctx, mode, data_len, ivec, data, data);
4242+ mbedtls_aes_free(&ctx);
4243+ return ret ? -1 : 0;
4244+}
4245+
4246+int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
4247+{
4248+ if (TEST_FAIL())
4249+ return -1;
4250+
4251+ return aes_128_cbc_oper(key, iv, data, data_len, MBEDTLS_AES_ENCRYPT);
4252+}
4253+
4254+int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
4255+{
4256+ if (TEST_FAIL())
4257+ return -1;
4258+
4259+ return aes_128_cbc_oper(key, iv, data, data_len, MBEDTLS_AES_DECRYPT);
4260+}
4261+
4262+
4263+/*
4264+ * Much of the following is documented in crypto.h as for CONFIG_TLS=internal
4265+ * but such comments are not accurate:
4266+ *
4267+ * "This function is only used with internal TLSv1 implementation
4268+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
4269+ * to implement this."
4270+ */
4271+
4272+
4273+#ifdef CRYPTO_MBEDTLS_CRYPTO_CIPHER
4274+
4275+#include <mbedtls/cipher.h>
4276+
4277+struct crypto_cipher
4278+{
4279+ mbedtls_cipher_context_t ctx_enc;
4280+ mbedtls_cipher_context_t ctx_dec;
4281+};
4282+
4283+struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
4284+ const u8 *iv, const u8 *key,
4285+ size_t key_len)
4286+{
4287+ /* IKEv2 src/eap_common/ikev2_common.c:ikev2_{encr,decr}_encrypt()
4288+ * uses one of CRYPTO_CIPHER_ALG_AES or CRYPTO_CIPHER_ALG_3DES */
4289+
4290+ mbedtls_cipher_type_t cipher_type;
4291+ size_t iv_len;
4292+ switch (alg) {
4293+ #ifdef MBEDTLS_ARC4_C
4294+ #if 0
4295+ case CRYPTO_CIPHER_ALG_RC4:
4296+ cipher_type = MBEDTLS_CIPHER_ARC4_128;
4297+ iv_len = 0;
4298+ break;
4299+ #endif
4300+ #endif
4301+ #ifdef MBEDTLS_AES_C
4302+ case CRYPTO_CIPHER_ALG_AES:
4303+ if (key_len == 16) cipher_type = MBEDTLS_CIPHER_AES_128_CTR;
4304+ if (key_len == 24) cipher_type = MBEDTLS_CIPHER_AES_192_CTR;
4305+ if (key_len == 32) cipher_type = MBEDTLS_CIPHER_AES_256_CTR;
4306+ iv_len = 16;
4307+ break;
4308+ #endif
4309+ #ifdef MBEDTLS_DES_C
4310+ case CRYPTO_CIPHER_ALG_3DES:
4311+ cipher_type = MBEDTLS_CIPHER_DES_EDE3_CBC;
4312+ iv_len = 8;
4313+ break;
4314+ #if 0
4315+ case CRYPTO_CIPHER_ALG_DES:
4316+ cipher_type = MBEDTLS_CIPHER_DES_CBC;
4317+ iv_len = 8;
4318+ break;
4319+ #endif
4320+ #endif
4321+ default:
4322+ return NULL;
4323+ }
4324+
4325+ const mbedtls_cipher_info_t *cipher_info;
4326+ cipher_info = mbedtls_cipher_info_from_type(cipher_type);
4327+ if (cipher_info == NULL)
4328+ return NULL;
4329+
4330+ key_len *= 8; /* key_bitlen */
4331+ #if 0 /*(were key_bitlen not already available)*/
4332+ #if MBEDTLS_VERSION_NUMBER >= 0x03010000 /* mbedtls 3.1.0 */
4333+ key_len = mbedtls_cipher_info_get_key_bitlen(cipher_info);
4334+ #else
4335+ key_len = cipher_info->MBEDTLS_PRIVATE(key_bitlen);
4336+ #endif
4337+ #endif
4338+
4339+ #if 0 /*(were iv_len not known above, would need MBEDTLS_PRIVATE(iv_size))*/
4340+ iv_len = cipher_info->MBEDTLS_PRIVATE(iv_size);
4341+ #endif
4342+
4343+ struct crypto_cipher *ctx = os_malloc(sizeof(*ctx));
4344+ if (!ctx)
4345+ return NULL;
4346+
4347+ mbedtls_cipher_init(&ctx->ctx_enc);
4348+ mbedtls_cipher_init(&ctx->ctx_dec);
4349+ if ( mbedtls_cipher_setup(&ctx->ctx_enc,cipher_info) == 0
4350+ && mbedtls_cipher_setup(&ctx->ctx_dec,cipher_info) == 0
4351+ && mbedtls_cipher_setkey(&ctx->ctx_enc,key,key_len,MBEDTLS_ENCRYPT) == 0
4352+ && mbedtls_cipher_setkey(&ctx->ctx_dec,key,key_len,MBEDTLS_DECRYPT) == 0
4353+ && mbedtls_cipher_set_iv(&ctx->ctx_enc,iv,iv_len) == 0
4354+ && mbedtls_cipher_set_iv(&ctx->ctx_dec,iv,iv_len) == 0
4355+ && mbedtls_cipher_reset(&ctx->ctx_enc) == 0
4356+ && mbedtls_cipher_reset(&ctx->ctx_dec) == 0) {
4357+ return ctx;
4358+ }
4359+
4360+ mbedtls_cipher_free(&ctx->ctx_enc);
4361+ mbedtls_cipher_free(&ctx->ctx_dec);
4362+ os_free(ctx);
4363+ return NULL;
4364+}
4365+
4366+int crypto_cipher_encrypt(struct crypto_cipher *ctx,
4367+ const u8 *plain, u8 *crypt, size_t len)
4368+{
4369+ size_t olen = 0; /*(poor interface above; unknown size of u8 *crypt)*/
4370+ return (mbedtls_cipher_update(&ctx->ctx_enc, plain, len, crypt, &olen)
4371+ || mbedtls_cipher_finish(&ctx->ctx_enc, crypt + olen, &olen)) ? -1 : 0;
4372+}
4373+
4374+int crypto_cipher_decrypt(struct crypto_cipher *ctx,
4375+ const u8 *crypt, u8 *plain, size_t len)
4376+{
4377+ size_t olen = 0; /*(poor interface above; unknown size of u8 *plain)*/
4378+ return (mbedtls_cipher_update(&ctx->ctx_dec, crypt, len, plain, &olen)
4379+ || mbedtls_cipher_finish(&ctx->ctx_dec, plain + olen, &olen)) ? -1 : 0;
4380+}
4381+
4382+void crypto_cipher_deinit(struct crypto_cipher *ctx)
4383+{
4384+ mbedtls_cipher_free(&ctx->ctx_enc);
4385+ mbedtls_cipher_free(&ctx->ctx_dec);
4386+ os_free(ctx);
4387+}
4388+
4389+#endif /* CRYPTO_MBEDTLS_CRYPTO_CIPHER */
4390+
4391+
4392+#ifdef CRYPTO_MBEDTLS_CRYPTO_HASH
4393+
4394+struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
4395+ size_t key_len)
4396+{
4397+ mbedtls_md_type_t md_type;
4398+ int is_hmac = 0;
4399+
4400+ switch (alg) {
4401+ #ifdef MBEDTLS_MD5_C
4402+ case CRYPTO_HASH_ALG_MD5:
4403+ md_type = MBEDTLS_MD_MD5;
4404+ break;
4405+ #endif
4406+ #ifdef MBEDTLS_SHA1_C
4407+ case CRYPTO_HASH_ALG_SHA1:
4408+ md_type = MBEDTLS_MD_SHA1;
4409+ break;
4410+ #endif
4411+ #ifdef MBEDTLS_MD5_C
4412+ case CRYPTO_HASH_ALG_HMAC_MD5:
4413+ md_type = MBEDTLS_MD_MD5;
4414+ is_hmac = 1;
4415+ break;
4416+ #endif
4417+ #ifdef MBEDTLS_SHA1_C
4418+ case CRYPTO_HASH_ALG_HMAC_SHA1:
4419+ md_type = MBEDTLS_MD_SHA1;
4420+ is_hmac = 1;
4421+ break;
4422+ #endif
4423+ #ifdef MBEDTLS_SHA256_C
4424+ case CRYPTO_HASH_ALG_SHA256:
4425+ md_type = MBEDTLS_MD_SHA256;
4426+ break;
4427+ case CRYPTO_HASH_ALG_HMAC_SHA256:
4428+ md_type = MBEDTLS_MD_SHA256;
4429+ is_hmac = 1;
4430+ break;
4431+ #endif
4432+ #ifdef MBEDTLS_SHA512_C
4433+ case CRYPTO_HASH_ALG_SHA384:
4434+ md_type = MBEDTLS_MD_SHA384;
4435+ break;
4436+ case CRYPTO_HASH_ALG_SHA512:
4437+ md_type = MBEDTLS_MD_SHA512;
4438+ break;
4439+ #endif
4440+ default:
4441+ return NULL;
4442+ }
4443+
4444+ const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_type);
4445+ if (!md_info)
4446+ return NULL;
4447+
4448+ mbedtls_md_context_t *mctx = os_malloc(sizeof(*mctx));
4449+ if (mctx == NULL)
4450+ return NULL;
4451+
4452+ mbedtls_md_init(mctx);
4453+ if (mbedtls_md_setup(mctx, md_info, is_hmac) != 0) {
4454+ os_free(mctx);
4455+ return NULL;
4456+ }
4457+
4458+ if (is_hmac)
4459+ mbedtls_md_hmac_starts(mctx, key, key_len);
4460+ else
4461+ mbedtls_md_starts(mctx);
4462+ return (struct crypto_hash *)((uintptr_t)mctx | is_hmac);
4463+}
4464+
4465+void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
4466+{
4467+ mbedtls_md_context_t *mctx = (mbedtls_md_context_t*)((uintptr_t)ctx & ~1uL);
4468+ #if 0
4469+ /*(mbedtls_md_hmac_update() and mbedtls_md_update()
4470+ * make same modifications under the hood in mbedtls)*/
4471+ if ((uintptr_t)ctx & 1uL)
4472+ mbedtls_md_hmac_update(mctx, data, len);
4473+ else
4474+ #endif
4475+ mbedtls_md_update(mctx, data, len);
4476+}
4477+
4478+int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
4479+{
4480+ mbedtls_md_context_t *mctx = (mbedtls_md_context_t*)((uintptr_t)ctx & ~1uL);
4481+ if (mac != NULL && len != NULL) { /*(NULL if caller just freeing context)*/
4482+ #if MBEDTLS_VERSION_NUMBER >= 0x03020000 /* mbedtls 3.2.0 */
4483+ const mbedtls_md_info_t *md_info = mbedtls_md_info_from_ctx(mctx);
4484+ #else
4485+ const mbedtls_md_info_t *md_info = mctx->MBEDTLS_PRIVATE(md_info);
4486+ #endif
4487+ size_t maclen = mbedtls_md_get_size(md_info);
4488+ if (*len < maclen) {
4489+ *len = maclen;
4490+ /*(note: ctx not freed; can call again with larger *len)*/
4491+ return -1;
4492+ }
4493+ *len = maclen;
4494+ if ((uintptr_t)ctx & 1uL)
4495+ mbedtls_md_hmac_finish(mctx, mac);
4496+ else
4497+ mbedtls_md_finish(mctx, mac);
4498+ }
4499+ mbedtls_md_free(mctx);
4500+ os_free(mctx);
4501+
4502+ if (TEST_FAIL())
4503+ return -1;
4504+
4505+ return 0;
4506+}
4507+
4508+#endif /* CRYPTO_MBEDTLS_CRYPTO_HASH */
4509+
4510+
4511+#ifdef CRYPTO_MBEDTLS_CRYPTO_BIGNUM
4512+
4513+#include <mbedtls/bignum.h>
4514+
4515+/* crypto.h bignum interfaces */
4516+
4517+struct crypto_bignum *crypto_bignum_init(void)
4518+{
4519+ if (TEST_FAIL())
4520+ return NULL;
4521+
4522+ mbedtls_mpi *bn = os_malloc(sizeof(*bn));
4523+ if (bn)
4524+ mbedtls_mpi_init(bn);
4525+ return (struct crypto_bignum *)bn;
4526+}
4527+
4528+struct crypto_bignum *crypto_bignum_init_set(const u8 *buf, size_t len)
4529+{
4530+ if (TEST_FAIL())
4531+ return NULL;
4532+
4533+ mbedtls_mpi *bn = os_malloc(sizeof(*bn));
4534+ if (bn) {
4535+ mbedtls_mpi_init(bn);
4536+ if (mbedtls_mpi_read_binary(bn, buf, len) == 0)
4537+ return (struct crypto_bignum *)bn;
4538+ }
4539+
4540+ os_free(bn);
4541+ return NULL;
4542+}
4543+
4544+struct crypto_bignum *crypto_bignum_init_uint(unsigned int val)
4545+{
4546+ if (TEST_FAIL())
4547+ return NULL;
4548+
4549+ #if 0 /*(hostap use of this interface passes int, not uint)*/
4550+ val = host_to_be32(val);
4551+ return crypto_bignum_init_set((const u8 *)&val, sizeof(val));
4552+ #else
4553+ mbedtls_mpi *bn = os_malloc(sizeof(*bn));
4554+ if (bn) {
4555+ mbedtls_mpi_init(bn);
4556+ if (mbedtls_mpi_lset(bn, (int)val) == 0)
4557+ return (struct crypto_bignum *)bn;
4558+ }
4559+
4560+ os_free(bn);
4561+ return NULL;
4562+ #endif
4563+}
4564+
4565+void crypto_bignum_deinit(struct crypto_bignum *n, int clear)
4566+{
4567+ mbedtls_mpi_free((mbedtls_mpi *)n);
4568+ os_free(n);
4569+}
4570+
4571+int crypto_bignum_to_bin(const struct crypto_bignum *a,
4572+ u8 *buf, size_t buflen, size_t padlen)
4573+{
4574+ if (TEST_FAIL())
4575+ return -1;
4576+
4577+ size_t n = mbedtls_mpi_size((mbedtls_mpi *)a);
4578+ if (n < padlen)
4579+ n = padlen;
4580+ return n > buflen || mbedtls_mpi_write_binary((mbedtls_mpi *)a, buf, n)
4581+ ? -1
4582+ : (int)(n);
4583+}
4584+
4585+int crypto_bignum_rand(struct crypto_bignum *r, const struct crypto_bignum *m)
4586+{
4587+ if (TEST_FAIL())
4588+ return -1;
4589+
4590+ /*assert(r != m);*//* r must not be same as m for mbedtls_mpi_random()*/
4591+ #if MBEDTLS_VERSION_NUMBER >= 0x021B0000 /* mbedtls 2.27.0 */
4592+ return mbedtls_mpi_random((mbedtls_mpi *)r, 0, (mbedtls_mpi *)m,
4593+ mbedtls_ctr_drbg_random,
4594+ crypto_mbedtls_ctr_drbg()) ? -1 : 0;
4595+ #else
4596+ /* (needed by EAP_PWD, SAE, DPP) */
4597+ wpa_printf(MSG_ERROR,
4598+ "mbedtls 2.27.0 or later required for mbedtls_mpi_random()");
4599+ return -1;
4600+ #endif
4601+}
4602+
4603+int crypto_bignum_add(const struct crypto_bignum *a,
4604+ const struct crypto_bignum *b,
4605+ struct crypto_bignum *c)
4606+{
4607+ return mbedtls_mpi_add_mpi((mbedtls_mpi *)c,
4608+ (const mbedtls_mpi *)a,
4609+ (const mbedtls_mpi *)b) ? -1 : 0;
4610+}
4611+
4612+int crypto_bignum_mod(const struct crypto_bignum *a,
4613+ const struct crypto_bignum *b,
4614+ struct crypto_bignum *c)
4615+{
4616+ return mbedtls_mpi_mod_mpi((mbedtls_mpi *)c,
4617+ (const mbedtls_mpi *)a,
4618+ (const mbedtls_mpi *)b) ? -1 : 0;
4619+}
4620+
4621+int crypto_bignum_exptmod(const struct crypto_bignum *a,
4622+ const struct crypto_bignum *b,
4623+ const struct crypto_bignum *c,
4624+ struct crypto_bignum *d)
4625+{
4626+ if (TEST_FAIL())
4627+ return -1;
4628+
4629+ /* (check if input params match d; d is the result) */
4630+ /* (a == d) is ok in current mbedtls implementation */
4631+ if (b == d || c == d) { /*(not ok; store result in intermediate)*/
4632+ mbedtls_mpi R;
4633+ mbedtls_mpi_init(&R);
4634+ int rc = mbedtls_mpi_exp_mod(&R,
4635+ (const mbedtls_mpi *)a,
4636+ (const mbedtls_mpi *)b,
4637+ (const mbedtls_mpi *)c,
4638+ NULL)
4639+ || mbedtls_mpi_copy((mbedtls_mpi *)d, &R) ? -1 : 0;
4640+ mbedtls_mpi_free(&R);
4641+ return rc;
4642+ }
4643+ else {
4644+ return mbedtls_mpi_exp_mod((mbedtls_mpi *)d,
4645+ (const mbedtls_mpi *)a,
4646+ (const mbedtls_mpi *)b,
4647+ (const mbedtls_mpi *)c,
4648+ NULL) ? -1 : 0;
4649+ }
4650+}
4651+
4652+int crypto_bignum_inverse(const struct crypto_bignum *a,
4653+ const struct crypto_bignum *b,
4654+ struct crypto_bignum *c)
4655+{
4656+ if (TEST_FAIL())
4657+ return -1;
4658+
4659+ return mbedtls_mpi_inv_mod((mbedtls_mpi *)c,
4660+ (const mbedtls_mpi *)a,
4661+ (const mbedtls_mpi *)b) ? -1 : 0;
4662+}
4663+
4664+int crypto_bignum_sub(const struct crypto_bignum *a,
4665+ const struct crypto_bignum *b,
4666+ struct crypto_bignum *c)
4667+{
4668+ if (TEST_FAIL())
4669+ return -1;
4670+
4671+ return mbedtls_mpi_sub_mpi((mbedtls_mpi *)c,
4672+ (const mbedtls_mpi *)a,
4673+ (const mbedtls_mpi *)b) ? -1 : 0;
4674+}
4675+
4676+int crypto_bignum_div(const struct crypto_bignum *a,
4677+ const struct crypto_bignum *b,
4678+ struct crypto_bignum *c)
4679+{
4680+ if (TEST_FAIL())
4681+ return -1;
4682+
4683+ /*(most current use of this crypto.h interface has a == c (result),
4684+ * so store result in an intermediate to avoid overwritten input)*/
4685+ mbedtls_mpi R;
4686+ mbedtls_mpi_init(&R);
4687+ int rc = mbedtls_mpi_div_mpi(&R, NULL,
4688+ (const mbedtls_mpi *)a,
4689+ (const mbedtls_mpi *)b)
4690+ || mbedtls_mpi_copy((mbedtls_mpi *)c, &R) ? -1 : 0;
4691+ mbedtls_mpi_free(&R);
4692+ return rc;
4693+}
4694+
4695+int crypto_bignum_addmod(const struct crypto_bignum *a,
4696+ const struct crypto_bignum *b,
4697+ const struct crypto_bignum *c,
4698+ struct crypto_bignum *d)
4699+{
4700+ if (TEST_FAIL())
4701+ return -1;
4702+
4703+ return mbedtls_mpi_add_mpi((mbedtls_mpi *)d,
4704+ (const mbedtls_mpi *)a,
4705+ (const mbedtls_mpi *)b)
4706+ || mbedtls_mpi_mod_mpi((mbedtls_mpi *)d,
4707+ (mbedtls_mpi *)d,
4708+ (const mbedtls_mpi *)c) ? -1 : 0;
4709+}
4710+
4711+int crypto_bignum_mulmod(const struct crypto_bignum *a,
4712+ const struct crypto_bignum *b,
4713+ const struct crypto_bignum *c,
4714+ struct crypto_bignum *d)
4715+{
4716+ if (TEST_FAIL())
4717+ return -1;
4718+
4719+ return mbedtls_mpi_mul_mpi((mbedtls_mpi *)d,
4720+ (const mbedtls_mpi *)a,
4721+ (const mbedtls_mpi *)b)
4722+ || mbedtls_mpi_mod_mpi((mbedtls_mpi *)d,
4723+ (mbedtls_mpi *)d,
4724+ (const mbedtls_mpi *)c) ? -1 : 0;
4725+}
4726+
4727+int crypto_bignum_sqrmod(const struct crypto_bignum *a,
4728+ const struct crypto_bignum *b,
4729+ struct crypto_bignum *c)
4730+{
4731+ if (TEST_FAIL())
4732+ return -1;
4733+
4734+ #if 1
4735+ return crypto_bignum_mulmod(a, a, b, c);
4736+ #else
4737+ mbedtls_mpi bn;
4738+ mbedtls_mpi_init(&bn);
4739+ if (mbedtls_mpi_lset(&bn, 2)) /* alt?: mbedtls_mpi_set_bit(&bn, 1) */
4740+ return -1;
4741+ int ret = mbedtls_mpi_exp_mod((mbedtls_mpi *)c,
4742+ (const mbedtls_mpi *)a, &bn,
4743+ (const mbedtls_mpi *)b, NULL) ? -1 : 0;
4744+ mbedtls_mpi_free(&bn);
4745+ return ret;
4746+ #endif
4747+}
4748+
4749+int crypto_bignum_rshift(const struct crypto_bignum *a, int n,
4750+ struct crypto_bignum *r)
4751+{
4752+ return mbedtls_mpi_copy((mbedtls_mpi *)r, (const mbedtls_mpi *)a)
4753+ || mbedtls_mpi_shift_r((mbedtls_mpi *)r, n) ? -1 : 0;
4754+}
4755+
4756+int crypto_bignum_cmp(const struct crypto_bignum *a,
4757+ const struct crypto_bignum *b)
4758+{
4759+ return mbedtls_mpi_cmp_mpi((const mbedtls_mpi *)a, (const mbedtls_mpi *)b);
4760+}
4761+
4762+int crypto_bignum_is_zero(const struct crypto_bignum *a)
4763+{
4764+ /* XXX: src/common/sae.c:sswu() contains comment:
4765+ * "TODO: Make sure crypto_bignum_is_zero() is constant time"
4766+ * Note: mbedtls_mpi_cmp_int() *is not* constant time */
4767+ return (mbedtls_mpi_cmp_int((const mbedtls_mpi *)a, 0) == 0);
4768+}
4769+
4770+int crypto_bignum_is_one(const struct crypto_bignum *a)
4771+{
4772+ return (mbedtls_mpi_cmp_int((const mbedtls_mpi *)a, 1) == 0);
4773+}
4774+
4775+int crypto_bignum_is_odd(const struct crypto_bignum *a)
4776+{
4777+ return mbedtls_mpi_get_bit((const mbedtls_mpi *)a, 0);
4778+}
4779+
4780+#include "utils/const_time.h"
4781+int crypto_bignum_legendre(const struct crypto_bignum *a,
4782+ const struct crypto_bignum *p)
4783+{
4784+ if (TEST_FAIL())
4785+ return -2;
4786+
4787+ /* Security Note:
4788+ * mbedtls_mpi_exp_mod() is not documented to run in constant time,
4789+ * though mbedtls/library/bignum.c uses constant_time_internal.h funcs.
4790+ * Compare to crypto_openssl.c:crypto_bignum_legendre()
4791+ * which uses openssl BN_mod_exp_mont_consttime()
4792+ * mbedtls/library/ecp.c has further countermeasures to timing attacks,
4793+ * (but ecp.c funcs are not used here) */
4794+
4795+ mbedtls_mpi exp, tmp;
4796+ mbedtls_mpi_init(&exp);
4797+ mbedtls_mpi_init(&tmp);
4798+
4799+ /* exp = (p-1) / 2 */
4800+ int res;
4801+ if (mbedtls_mpi_sub_int(&exp, (const mbedtls_mpi *)p, 1) == 0
4802+ && mbedtls_mpi_shift_r(&exp, 1) == 0
4803+ && mbedtls_mpi_exp_mod(&tmp, (const mbedtls_mpi *)a, &exp,
4804+ (const mbedtls_mpi *)p, NULL) == 0) {
4805+ /*(modified from crypto_openssl.c:crypto_bignum_legendre())*/
4806+ /* Return 1 if tmp == 1, 0 if tmp == 0, or -1 otherwise. Need
4807+ * to use constant time selection to avoid branches here. */
4808+ unsigned int mask;
4809+ res = -1;
4810+ mask = const_time_eq((mbedtls_mpi_cmp_int(&tmp, 1) == 0), 1);
4811+ res = const_time_select_int(mask, 1, res);
4812+ mask = const_time_eq((mbedtls_mpi_cmp_int(&tmp, 0) == 0), 1);
4813+ res = const_time_select_int(mask, 0, res);
4814+ } else {
4815+ res = -2;
4816+ }
4817+
4818+ mbedtls_mpi_free(&tmp);
4819+ mbedtls_mpi_free(&exp);
4820+ return res;
4821+}
4822+
4823+#endif /* CRYPTO_MBEDTLS_CRYPTO_BIGNUM */
4824+
4825+
4826+#ifdef CRYPTO_MBEDTLS_CRYPTO_DH
4827+
4828+/* crypto_internal-modexp.c */
4829+
4830+#include <mbedtls/bignum.h>
4831+#include <mbedtls/dhm.h>
4832+
4833+#if 0 /* crypto_dh_init() and crypto_dh_derive_secret() prefer to use mbedtls */
4834+int crypto_mod_exp(const u8 *base, size_t base_len,
4835+ const u8 *power, size_t power_len,
4836+ const u8 *modulus, size_t modulus_len,
4837+ u8 *result, size_t *result_len)
4838+{
4839+ if (TEST_FAIL())
4840+ return -1;
4841+
4842+ mbedtls_mpi bn_base, bn_exp, bn_modulus, bn_result;
4843+ mbedtls_mpi_init(&bn_base);
4844+ mbedtls_mpi_init(&bn_exp);
4845+ mbedtls_mpi_init(&bn_modulus);
4846+ mbedtls_mpi_init(&bn_result);
4847+
4848+ size_t len;
4849+ int ret = mbedtls_mpi_read_binary(&bn_base, base, base_len)
4850+ || mbedtls_mpi_read_binary(&bn_exp, power, power_len)
4851+ || mbedtls_mpi_read_binary(&bn_modulus, modulus, modulus_len)
4852+ || mbedtls_mpi_exp_mod(&bn_result,&bn_base,&bn_exp,&bn_modulus,NULL)
4853+ || (len = mbedtls_mpi_size(&bn_result)) > *result_len
4854+ || mbedtls_mpi_write_binary(&bn_result, result, (*result_len = len))
4855+ ? -1
4856+ : 0;
4857+
4858+ mbedtls_mpi_free(&bn_base);
4859+ mbedtls_mpi_free(&bn_exp);
4860+ mbedtls_mpi_free(&bn_modulus);
4861+ mbedtls_mpi_free(&bn_result);
4862+ return ret;
4863+}
4864+#endif
4865+
4866+static int crypto_mbedtls_dh_set_bin_pg(mbedtls_dhm_context *ctx, u8 generator,
4867+ const u8 *prime, size_t prime_len)
4868+{
4869+ /*(could set these directly in MBEDTLS_PRIVATE members)*/
4870+ mbedtls_mpi P, G;
4871+ mbedtls_mpi_init(&P);
4872+ mbedtls_mpi_init(&G);
4873+ int ret = mbedtls_mpi_lset(&G, generator)
4874+ || mbedtls_mpi_read_binary(&P, prime, prime_len)
4875+ || mbedtls_dhm_set_group(ctx, &P, &G);
4876+ mbedtls_mpi_free(&P);
4877+ mbedtls_mpi_free(&G);
4878+ return ret;
4879+}
4880+
4881+__attribute_noinline__
4882+static int crypto_mbedtls_dh_init_public(mbedtls_dhm_context *ctx, u8 generator,
4883+ const u8 *prime, size_t prime_len,
4884+ u8 *privkey, u8 *pubkey)
4885+{
4886+ if (crypto_mbedtls_dh_set_bin_pg(ctx, generator, prime, prime_len)
4887+ || mbedtls_dhm_make_public(ctx, (int)prime_len, pubkey, prime_len,
4888+ mbedtls_ctr_drbg_random,
4889+ crypto_mbedtls_ctr_drbg()))
4890+ return -1;
4891+
4892+ /*(enable later when upstream mbedtls interface changes require)*/
4893+ #if 0 && MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
4894+ mbedtls_mpi X;
4895+ mbedtls_mpi_init(&X);
4896+ int ret = mbedtls_dhm_get_value(ctx, MBEDTLS_DHM_PARAM_X, &X)
4897+ || mbedtls_mpi_write_binary(&X, privkey, prime_len) ? -1 : 0;
4898+ mbedtls_mpi_free(&X);
4899+ return ret;
4900+ #else
4901+ return mbedtls_mpi_write_binary(&ctx->MBEDTLS_PRIVATE(X),
4902+ privkey, prime_len) ? -1 : 0;
4903+ #endif
4904+}
4905+
4906+int crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey,
4907+ u8 *pubkey)
4908+{
4909+ if (TEST_FAIL())
4910+ return -1;
4911+
4912+ #if 0 /*(crypto_dh_init() duplicated (and identical) in crypto_*.c modules)*/
4913+ size_t pubkey_len, pad;
4914+
4915+ if (os_get_random(privkey, prime_len) < 0)
4916+ return -1;
4917+ if (os_memcmp(privkey, prime, prime_len) > 0) {
4918+ /* Make sure private value is smaller than prime */
4919+ privkey[0] = 0;
4920+ }
4921+
4922+ pubkey_len = prime_len;
4923+ if (crypto_mod_exp(&generator, 1, privkey, prime_len, prime, prime_len,
4924+ pubkey, &pubkey_len) < 0)
4925+ return -1;
4926+ if (pubkey_len < prime_len) {
4927+ pad = prime_len - pubkey_len;
4928+ os_memmove(pubkey + pad, pubkey, pubkey_len);
4929+ os_memset(pubkey, 0, pad);
4930+ }
4931+
4932+ return 0;
4933+ #else
4934+ /* Prefer to use mbedtls to derive our public/private key, as doing so
4935+ * leverages mbedtls to properly format output and to perform blinding*/
4936+ mbedtls_dhm_context ctx;
4937+ mbedtls_dhm_init(&ctx);
4938+ int ret = crypto_mbedtls_dh_init_public(&ctx, generator, prime,
4939+ prime_len, privkey, pubkey);
4940+ mbedtls_dhm_free(&ctx);
4941+ return ret;
4942+ #endif
4943+}
4944+
4945+/*(crypto_dh_derive_secret() could be implemented using crypto.h APIs
4946+ * instead of being reimplemented in each crypto_*.c)*/
4947+int crypto_dh_derive_secret(u8 generator, const u8 *prime, size_t prime_len,
4948+ const u8 *order, size_t order_len,
4949+ const u8 *privkey, size_t privkey_len,
4950+ const u8 *pubkey, size_t pubkey_len,
4951+ u8 *secret, size_t *len)
4952+{
4953+ if (TEST_FAIL())
4954+ return -1;
4955+
4956+ #if 0
4957+ if (pubkey_len > prime_len ||
4958+ (pubkey_len == prime_len &&
4959+ os_memcmp(pubkey, prime, prime_len) >= 0))
4960+ return -1;
4961+
4962+ int res = 0;
4963+ mbedtls_mpi pub;
4964+ mbedtls_mpi_init(&pub);
4965+ if (mbedtls_mpi_read_binary(&pub, pubkey, pubkey_len)
4966+ || mbedtls_mpi_cmp_int(&pub, 1) <= 0) {
4967+ res = -1;
4968+ } else if (order) {
4969+ mbedtls_mpi p, q, tmp;
4970+ mbedtls_mpi_init(&p);
4971+ mbedtls_mpi_init(&q);
4972+ mbedtls_mpi_init(&tmp);
4973+
4974+ /* verify: pubkey^q == 1 mod p */
4975+ res = (mbedtls_mpi_read_binary(&p, prime, prime_len)
4976+ || mbedtls_mpi_read_binary(&q, order, order_len)
4977+ || mbedtls_mpi_exp_mod(&tmp, &pub, &q, &p, NULL)
4978+ || mbedtls_mpi_cmp_int(&tmp, 1) != 0);
4979+
4980+ mbedtls_mpi_free(&p);
4981+ mbedtls_mpi_free(&q);
4982+ mbedtls_mpi_free(&tmp);
4983+ }
4984+ mbedtls_mpi_free(&pub);
4985+
4986+ return (res == 0)
4987+ ? crypto_mod_exp(pubkey, pubkey_len, privkey, privkey_len,
4988+ prime, prime_len, secret, len)
4989+ : -1;
4990+ #else
4991+ /* Prefer to use mbedtls to derive DH shared secret, as doing so
4992+ * leverages mbedtls to validate params and to perform blinding.
4993+ *
4994+ * Attempt to reconstitute DH context to derive shared secret
4995+ * (due to limitations of the interface, which ought to pass context).
4996+ * Force provided G (our private key) into context without validation.
4997+ * Regenerating GX (our public key) not needed to derive shared secret.
4998+ */
4999+ /*(older compilers might not support VLAs)*/
5000+ /*unsigned char buf[2+prime_len+2+1+2+pubkey_len];*/
5001+ unsigned char buf[2+MBEDTLS_MPI_MAX_SIZE+2+1+2+MBEDTLS_MPI_MAX_SIZE];
5002+ unsigned char *p = buf + 2 + prime_len;
5003+ if (2+prime_len+2+1+2+pubkey_len > sizeof(buf))
5004+ return -1;
5005+ WPA_PUT_BE16(buf, prime_len); /*(2-byte big-endian size of prime)*/
5006+ p[0] = 0; /*(2-byte big-endian size of generator)*/
5007+ p[1] = 1;
5008+ p[2] = generator;
5009+ WPA_PUT_BE16(p+3, pubkey_len); /*(2-byte big-endian size of pubkey)*/
5010+ os_memcpy(p+5, pubkey, pubkey_len);
5011+ os_memcpy(buf+2, prime, prime_len);
5012+
5013+ mbedtls_dhm_context ctx;
5014+ mbedtls_dhm_init(&ctx);
5015+ p = buf;
5016+ int ret = mbedtls_dhm_read_params(&ctx, &p, p+2+prime_len+5+pubkey_len)
5017+ || mbedtls_mpi_read_binary(&ctx.MBEDTLS_PRIVATE(X),
5018+ privkey, privkey_len)
5019+ || mbedtls_dhm_calc_secret(&ctx, secret, *len, len,
5020+ mbedtls_ctr_drbg_random,
5021+ crypto_mbedtls_ctr_drbg()) ? -1 : 0;
5022+ mbedtls_dhm_free(&ctx);
5023+ return ret;
5024+ #endif
5025+}
5026+
5027+/* dh_group5.c */
5028+
5029+#include "dh_group5.h"
5030+
5031+/* RFC3526_PRIME_1536[] and RFC3526_GENERATOR_1536[] from crypto_wolfssl.c */
5032+
5033+static const unsigned char RFC3526_PRIME_1536[] = {
5034+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
5035+ 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
5036+ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
5037+ 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
5038+ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
5039+ 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
5040+ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
5041+ 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
5042+ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
5043+ 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
5044+ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
5045+ 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
5046+ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
5047+ 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
5048+ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
5049+ 0xCA, 0x23, 0x73, 0x27, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
5050+};
5051+
5052+static const unsigned char RFC3526_GENERATOR_1536[] = {
5053+ 0x02
5054+};
5055+
5056+void * dh5_init(struct wpabuf **priv, struct wpabuf **publ)
5057+{
5058+ const unsigned char * const prime = RFC3526_PRIME_1536;
5059+ const size_t prime_len = sizeof(RFC3526_PRIME_1536);
5060+ const u8 generator = *RFC3526_GENERATOR_1536;
5061+ struct wpabuf *wpubl = NULL, *wpriv = NULL;
5062+
5063+ mbedtls_dhm_context *ctx = os_malloc(sizeof(*ctx));
5064+ if (ctx == NULL)
5065+ return NULL;
5066+ mbedtls_dhm_init(ctx);
5067+
5068+ if ( (wpubl = wpabuf_alloc(prime_len))
5069+ && (wpriv = wpabuf_alloc(prime_len))
5070+ && crypto_mbedtls_dh_init_public(ctx, generator, prime, prime_len,
5071+ wpabuf_put(wpriv, prime_len),
5072+ wpabuf_put(wpubl, prime_len))==0) {
5073+ wpabuf_free(*publ);
5074+ wpabuf_clear_free(*priv);
5075+ *publ = wpubl;
5076+ *priv = wpriv;
5077+ return ctx;
5078+ }
5079+
5080+ wpabuf_clear_free(wpriv);
5081+ wpabuf_free(wpubl);
5082+ mbedtls_dhm_free(ctx);
5083+ os_free(ctx);
5084+ return NULL;
5085+}
5086+
5087+#ifdef CRYPTO_MBEDTLS_DH5_INIT_FIXED
5088+void * dh5_init_fixed(const struct wpabuf *priv, const struct wpabuf *publ)
5089+{
5090+ const unsigned char * const prime = RFC3526_PRIME_1536;
5091+ const size_t prime_len = sizeof(RFC3526_PRIME_1536);
5092+ const u8 generator = *RFC3526_GENERATOR_1536;
5093+
5094+ mbedtls_dhm_context *ctx = os_malloc(sizeof(*ctx));
5095+ if (ctx == NULL)
5096+ return NULL;
5097+ mbedtls_dhm_init(ctx);
5098+
5099+ if (crypto_mbedtls_dh_set_bin_pg(ctx, generator, prime, prime_len)==0
5100+ #if 0 /*(ignore; not required to derive shared secret)*/
5101+ && mbedtls_mpi_read_binary(&ctx->MBEDTLS_PRIVATE(GX),
5102+ wpabuf_head(publ),wpabuf_len(publ))==0
5103+ #endif
5104+ && mbedtls_mpi_read_binary(&ctx->MBEDTLS_PRIVATE(X),
5105+ wpabuf_head(priv),wpabuf_len(priv))==0) {
5106+ return ctx;
5107+ }
5108+
5109+ mbedtls_dhm_free(ctx);
5110+ os_free(ctx);
5111+ return NULL;
5112+}
5113+#endif
5114+
5115+struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public,
5116+ const struct wpabuf *own_private)
5117+{
5118+ /*((mbedtls_dhm_context *)ctx must already contain own_private)*/
5119+ /* mbedtls 2.x: prime_len = ctx->len; */
5120+ /* mbedtls 3.x: prime_len = mbedtls_dhm_get_len(ctx); */
5121+ size_t olen = sizeof(RFC3526_PRIME_1536); /*(sizeof(); prime known)*/
5122+ struct wpabuf *buf = wpabuf_alloc(olen);
5123+ if (buf == NULL)
5124+ return NULL;
5125+ if (mbedtls_dhm_read_public((mbedtls_dhm_context *)ctx,
5126+ wpabuf_head(peer_public),
5127+ wpabuf_len(peer_public)) == 0
5128+ && mbedtls_dhm_calc_secret(ctx, wpabuf_mhead(buf), olen, &olen,
5129+ mbedtls_ctr_drbg_random,
5130+ crypto_mbedtls_ctr_drbg()) == 0) {
5131+ wpabuf_put(buf, olen);
5132+ return buf;
5133+ }
5134+
5135+ wpabuf_free(buf);
5136+ return NULL;
5137+}
5138+
5139+void dh5_free(void *ctx)
5140+{
5141+ mbedtls_dhm_free(ctx);
5142+ os_free(ctx);
5143+}
5144+
5145+#endif /* CRYPTO_MBEDTLS_CRYPTO_DH */
5146+
5147+
5148+#if defined(CRYPTO_MBEDTLS_CRYPTO_ECDH) || defined(CRYPTO_MBEDTLS_CRYPTO_EC)
5149+
5150+#include <mbedtls/ecp.h>
5151+
5152+#define CRYPTO_EC_pbits(e) (((mbedtls_ecp_group *)(e))->pbits)
5153+#define CRYPTO_EC_plen(e) ((((mbedtls_ecp_group *)(e))->pbits+7)>>3)
5154+#define CRYPTO_EC_P(e) (&((mbedtls_ecp_group *)(e))->P)
5155+#define CRYPTO_EC_N(e) (&((mbedtls_ecp_group *)(e))->N)
5156+#define CRYPTO_EC_A(e) (&((mbedtls_ecp_group *)(e))->A)
5157+#define CRYPTO_EC_B(e) (&((mbedtls_ecp_group *)(e))->B)
5158+#define CRYPTO_EC_G(e) (&((mbedtls_ecp_group *)(e))->G)
5159+
5160+static mbedtls_ecp_group_id crypto_mbedtls_ecp_group_id_from_ike_id(int group)
5161+{
5162+ /* https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml */
5163+ switch (group) {
5164+ #ifdef MBEDTLS_ECP_DP_SECP256R1_ENABLED
5165+ case 19: return MBEDTLS_ECP_DP_SECP256R1;
5166+ #endif
5167+ #ifdef MBEDTLS_ECP_DP_SECP384R1_ENABLED
5168+ case 20: return MBEDTLS_ECP_DP_SECP384R1;
5169+ #endif
5170+ #ifdef MBEDTLS_ECP_DP_SECP521R1_ENABLED
5171+ case 21: return MBEDTLS_ECP_DP_SECP521R1;
5172+ #endif
5173+ #ifdef MBEDTLS_ECP_DP_SECP192R1_ENABLED
5174+ case 25: return MBEDTLS_ECP_DP_SECP192R1;
5175+ #endif
5176+ #ifdef MBEDTLS_ECP_DP_SECP224R1_ENABLED
5177+ case 26: return MBEDTLS_ECP_DP_SECP224R1;
5178+ #endif
5179+ #ifdef MBEDTLS_ECP_DP_BP256R1_ENABLED
5180+ case 28: return MBEDTLS_ECP_DP_BP256R1;
5181+ #endif
5182+ #ifdef MBEDTLS_ECP_DP_BP384R1_ENABLED
5183+ case 29: return MBEDTLS_ECP_DP_BP384R1;
5184+ #endif
5185+ #ifdef MBEDTLS_ECP_DP_BP512R1_ENABLED
5186+ case 30: return MBEDTLS_ECP_DP_BP512R1;
5187+ #endif
5188+ #ifdef MBEDTLS_ECP_DP_CURVE25519_ENABLED
5189+ case 31: return MBEDTLS_ECP_DP_CURVE25519;
5190+ #endif
5191+ #ifdef MBEDTLS_ECP_DP_CURVE448_ENABLED
5192+ case 32: return MBEDTLS_ECP_DP_CURVE448;
5193+ #endif
5194+ default: return MBEDTLS_ECP_DP_NONE;
5195+ }
5196+}
5197+
5198+#ifdef CRYPTO_MBEDTLS_CRYPTO_EC
5199+static int crypto_mbedtls_ike_id_from_ecp_group_id(mbedtls_ecp_group_id grp_id)
5200+{
5201+ /* https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml */
5202+ /*(for crypto_ec_key_group())*/
5203+ switch (grp_id) {
5204+ #ifdef MBEDTLS_ECP_DP_SECP256R1_ENABLED
5205+ case MBEDTLS_ECP_DP_SECP256R1: return 19;
5206+ #endif
5207+ #ifdef MBEDTLS_ECP_DP_SECP384R1_ENABLED
5208+ case MBEDTLS_ECP_DP_SECP384R1: return 20;
5209+ #endif
5210+ #ifdef MBEDTLS_ECP_DP_SECP521R1_ENABLED
5211+ case MBEDTLS_ECP_DP_SECP521R1: return 21;
5212+ #endif
5213+ #ifdef MBEDTLS_ECP_DP_SECP192R1_ENABLED
5214+ case MBEDTLS_ECP_DP_SECP192R1: return 25;
5215+ #endif
5216+ #ifdef MBEDTLS_ECP_DP_SECP224R1_ENABLED
5217+ case MBEDTLS_ECP_DP_SECP224R1: return 26;
5218+ #endif
5219+ #ifdef MBEDTLS_ECP_DP_BP256R1_ENABLED
5220+ case MBEDTLS_ECP_DP_BP256R1: return 28;
5221+ #endif
5222+ #ifdef MBEDTLS_ECP_DP_BP384R1_ENABLED
5223+ case MBEDTLS_ECP_DP_BP384R1: return 29;
5224+ #endif
5225+ #ifdef MBEDTLS_ECP_DP_BP512R1_ENABLED
5226+ case MBEDTLS_ECP_DP_BP512R1: return 30;
5227+ #endif
5228+ #ifdef MBEDTLS_ECP_DP_CURVE25519_ENABLED
5229+ case MBEDTLS_ECP_DP_CURVE25519: return 31;
5230+ #endif
5231+ #ifdef MBEDTLS_ECP_DP_CURVE448_ENABLED
5232+ case MBEDTLS_ECP_DP_CURVE448: return 32;
5233+ #endif
5234+ default: return -1;
5235+ }
5236+}
5237+#endif
5238+
5239+#endif /* CRYPTO_MBEDTLS_CRYPTO_ECDH || CRYPTO_MBEDTLS_CRYPTO_EC */
5240+
5241+
5242+#if defined(CRYPTO_MBEDTLS_CRYPTO_ECDH) || defined(CRYPTO_MBEDTLS_CRYPTO_EC_DPP)
5243+
5244+#include <mbedtls/ecp.h>
5245+#include <mbedtls/pk.h>
5246+
5247+static int crypto_mbedtls_keypair_gen(int group, mbedtls_pk_context *pk)
5248+{
5249+ mbedtls_ecp_group_id grp_id =
5250+ crypto_mbedtls_ecp_group_id_from_ike_id(group);
5251+ if (grp_id == MBEDTLS_ECP_DP_NONE)
5252+ return -1;
5253+ const mbedtls_pk_info_t *pk_info =
5254+ mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
5255+ if (pk_info == NULL)
5256+ return -1;
5257+ return mbedtls_pk_setup(pk, pk_info)
5258+ || mbedtls_ecp_gen_key(grp_id, mbedtls_pk_ec(*pk),
5259+ mbedtls_ctr_drbg_random,
5260+ crypto_mbedtls_ctr_drbg()) ? -1 : 0;
5261+}
5262+
5263+#endif
5264+
5265+
5266+#ifdef CRYPTO_MBEDTLS_CRYPTO_ECDH
5267+
5268+#include <mbedtls/ecdh.h>
5269+#include <mbedtls/ecdsa.h>
5270+#include <mbedtls/ecp.h>
5271+#include <mbedtls/pk.h>
5272+
5273+/* wrap mbedtls_ecdh_context for more future-proof direct access to components
5274+ * (mbedtls_ecdh_context internal implementation may change between releases)
5275+ *
5276+ * If mbedtls_pk_context -- specifically underlying mbedtls_ecp_keypair --
5277+ * lifetime were guaranteed to be longer than that of mbedtls_ecdh_context,
5278+ * then mbedtls_pk_context or mbedtls_ecp_keypair could be stored in crypto_ecdh
5279+ * (or crypto_ec_key could be stored in crypto_ecdh, and crypto_ec_key could
5280+ * wrap mbedtls_ecp_keypair and components, to avoid MBEDTLS_PRIVATE access) */
5281+struct crypto_ecdh {
5282+ mbedtls_ecdh_context ctx;
5283+ mbedtls_ecp_group grp;
5284+ mbedtls_ecp_point Q;
5285+};
5286+
5287+struct crypto_ecdh * crypto_ecdh_init(int group)
5288+{
5289+ mbedtls_pk_context pk;
5290+ mbedtls_pk_init(&pk);
5291+ struct crypto_ecdh *ecdh = crypto_mbedtls_keypair_gen(group, &pk) == 0
5292+ ? crypto_ecdh_init2(group, (struct crypto_ec_key *)&pk)
5293+ : NULL;
5294+ mbedtls_pk_free(&pk);
5295+ return ecdh;
5296+}
5297+
5298+struct crypto_ecdh * crypto_ecdh_init2(int group,
5299+ struct crypto_ec_key *own_key)
5300+{
5301+ mbedtls_ecp_group_id grp_id =
5302+ crypto_mbedtls_ecp_group_id_from_ike_id(group);
5303+ if (grp_id == MBEDTLS_ECP_DP_NONE)
5304+ return NULL;
5305+ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)own_key);
5306+ struct crypto_ecdh *ecdh = os_malloc(sizeof(*ecdh));
5307+ if (ecdh == NULL)
5308+ return NULL;
5309+ mbedtls_ecdh_init(&ecdh->ctx);
5310+ mbedtls_ecp_group_init(&ecdh->grp);
5311+ mbedtls_ecp_point_init(&ecdh->Q);
5312+ if (mbedtls_ecdh_setup(&ecdh->ctx, grp_id) == 0
5313+ && mbedtls_ecdh_get_params(&ecdh->ctx,ecp_kp,MBEDTLS_ECDH_OURS) == 0) {
5314+ /* copy grp and Q for later use
5315+ * (retrieving this info later is more convoluted
5316+ * even if mbedtls_ecdh_make_public() is considered)*/
5317+ #if MBEDTLS_VERSION_NUMBER >= 0x03020000 /* mbedtls 3.2.0 */
5318+ mbedtls_mpi d;
5319+ mbedtls_mpi_init(&d);
5320+ if (mbedtls_ecp_export(ecp_kp, &ecdh->grp, &d, &ecdh->Q) == 0) {
5321+ mbedtls_mpi_free(&d);
5322+ return ecdh;
5323+ }
5324+ mbedtls_mpi_free(&d);
5325+ #else
5326+ if (mbedtls_ecp_group_load(&ecdh->grp, grp_id) == 0
5327+ && mbedtls_ecp_copy(&ecdh->Q, &ecp_kp->MBEDTLS_PRIVATE(Q)) == 0)
5328+ return ecdh;
5329+ #endif
5330+ }
5331+
5332+ mbedtls_ecp_point_free(&ecdh->Q);
5333+ mbedtls_ecp_group_free(&ecdh->grp);
5334+ mbedtls_ecdh_free(&ecdh->ctx);
5335+ os_free(ecdh);
5336+ return NULL;
5337+}
5338+
5339+struct wpabuf * crypto_ecdh_get_pubkey(struct crypto_ecdh *ecdh, int inc_y)
5340+{
5341+ mbedtls_ecp_group *grp = &ecdh->grp;
5342+ size_t prime_len = CRYPTO_EC_plen(grp);
5343+ size_t output_len = prime_len;
5344+ u8 output_offset = 0;
5345+ u8 buf[256];
5346+
5347+ #ifdef MBEDTLS_ECP_MONTGOMERY_ENABLED
5348+ /* len */
5349+ #endif
5350+ #ifdef MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED
5351+ if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {
5352+ output_len = inc_y ? prime_len * 2 + 1 : prime_len + 1;
5353+ output_offset = 1;
5354+ }
5355+ #endif
5356+
5357+ if (output_len > sizeof(buf))
5358+ return NULL;
5359+
5360+ inc_y = inc_y ? MBEDTLS_ECP_PF_UNCOMPRESSED : MBEDTLS_ECP_PF_COMPRESSED;
5361+ if (mbedtls_ecp_point_write_binary(grp, &ecdh->Q, inc_y, &output_len,
5362+ buf, output_len) == 0) {
5363+ return wpabuf_alloc_copy(buf + output_offset, output_len - output_offset);
5364+ }
5365+
5366+ return NULL;
5367+}
5368+
5369+#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
5370+static int crypto_mbedtls_short_weierstrass_derive_y(mbedtls_ecp_group *grp,
5371+ mbedtls_mpi *bn,
5372+ int parity_bit)
5373+{
5374+ /* y^2 = x^3 + ax + b
5375+ * sqrt(w) = w^((p+1)/4) mod p (for prime p where p = 3 mod 4) */
5376+ mbedtls_mpi *cy2 = (mbedtls_mpi *)
5377+ crypto_ec_point_compute_y_sqr((struct crypto_ec *)grp,
5378+ (const struct crypto_bignum *)bn); /*x*/
5379+ if (cy2 == NULL)
5380+ return -1;
5381+
5382+ /*mbedtls_mpi_free(bn);*/
5383+ /*(reuse bn to store result (y))*/
5384+
5385+ mbedtls_mpi exp;
5386+ mbedtls_mpi_init(&exp);
5387+ int ret = mbedtls_mpi_get_bit(&grp->P, 0) != 1 /*(p = 3 mod 4)*/
5388+ || mbedtls_mpi_get_bit(&grp->P, 1) != 1 /*(p = 3 mod 4)*/
5389+ || mbedtls_mpi_add_int(&exp, &grp->P, 1)
5390+ || mbedtls_mpi_shift_r(&exp, 2)
5391+ || mbedtls_mpi_exp_mod(bn, cy2, &exp, &grp->P, NULL)
5392+ || (mbedtls_mpi_get_bit(bn, 0) != parity_bit
5393+ && mbedtls_mpi_sub_mpi(bn, &grp->P, bn));
5394+ mbedtls_mpi_free(&exp);
5395+ mbedtls_mpi_free(cy2);
5396+ os_free(cy2);
5397+ return ret;
5398+}
5399+#endif
5400+
5401+struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y,
5402+ const u8 *key, size_t len)
5403+{
5404+ if (len == 0) /*(invalid peer key)*/
5405+ return NULL;
5406+
5407+ mbedtls_ecp_group *grp = &ecdh->grp;
5408+
5409+ #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
5410+ if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {
5411+ /* add header for mbedtls_ecdh_read_public() */
5412+ u8 buf[256];
5413+ if (sizeof(buf)-1 < len)
5414+ return NULL;
5415+ buf[0] = (u8)(len);
5416+ os_memcpy(buf+1, key, len);
5417+
5418+ if (inc_y) {
5419+ if (!(len & 1)) { /*(dpp code/tests does not include tag?!?)*/
5420+ if (sizeof(buf)-2 < len)
5421+ return NULL;
5422+ buf[0] = (u8)(1+len);
5423+ buf[1] = 0x04;
5424+ os_memcpy(buf+2, key, len);
5425+ }
5426+ len >>= 1; /*(repurpose len to prime_len)*/
5427+ } else { /* (inc_y == 0) */
5428+ /* mbedtls_ecp_point_read_binary() does not currently support
5429+ * MBEDTLS_ECP_PF_COMPRESSED format (buf[1] = 0x02 or 0x03)
5430+ * (returns MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) */
5431+
5432+ /* derive y, amend buf[] with y for UNCOMPRESSED format */
5433+ if (sizeof(buf)-2 < len*2 || len == 0)
5434+ return NULL;
5435+
5436+ buf[0] = (u8)(1+len*2);
5437+ buf[1] = 0x04;
5438+ os_memcpy(buf+2, key, len);
5439+
5440+ mbedtls_mpi bn;
5441+ mbedtls_mpi_init(&bn);
5442+ int ret = mbedtls_mpi_read_binary(&bn, key, len)
5443+ || crypto_mbedtls_short_weierstrass_derive_y(grp, &bn, 0)
5444+ || mbedtls_mpi_write_binary(&bn, buf+2+len, len);
5445+ mbedtls_mpi_free(&bn);
5446+ if (ret != 0)
5447+ return NULL;
5448+ }
5449+
5450+ if (mbedtls_ecdh_read_public(&ecdh->ctx, buf, buf[0]+1))
5451+ return NULL;
5452+ }
5453+ #endif
5454+ #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
5455+ if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {
5456+ if (mbedtls_ecdh_read_public(&ecdh->ctx, key, len))
5457+ return NULL;
5458+ }
5459+ #endif
5460+
5461+ struct wpabuf *buf = wpabuf_alloc(len);
5462+ if (buf == NULL)
5463+ return NULL;
5464+
5465+ if (mbedtls_ecdh_calc_secret(&ecdh->ctx, &len,
5466+ wpabuf_mhead(buf), len,
5467+ mbedtls_ctr_drbg_random,
5468+ crypto_mbedtls_ctr_drbg()) == 0) {
5469+ wpabuf_put(buf, len);
5470+ return buf;
5471+ }
5472+
5473+ wpabuf_clear_free(buf);
5474+ return NULL;
5475+}
5476+
5477+void crypto_ecdh_deinit(struct crypto_ecdh *ecdh)
5478+{
5479+ if (ecdh == NULL)
5480+ return;
5481+ mbedtls_ecp_point_free(&ecdh->Q);
5482+ mbedtls_ecp_group_free(&ecdh->grp);
5483+ mbedtls_ecdh_free(&ecdh->ctx);
5484+ os_free(ecdh);
5485+}
5486+
5487+size_t crypto_ecdh_prime_len(struct crypto_ecdh *ecdh)
5488+{
5489+ return CRYPTO_EC_plen(&ecdh->grp);
5490+}
5491+
5492+#endif /* CRYPTO_MBEDTLS_CRYPTO_ECDH */
5493+
5494+
5495+#ifdef CRYPTO_MBEDTLS_CRYPTO_EC
5496+
5497+#include <mbedtls/ecp.h>
5498+
5499+struct crypto_ec *crypto_ec_init(int group)
5500+{
5501+ mbedtls_ecp_group_id grp_id =
5502+ crypto_mbedtls_ecp_group_id_from_ike_id(group);
5503+ if (grp_id == MBEDTLS_ECP_DP_NONE)
5504+ return NULL;
5505+ mbedtls_ecp_group *e = os_malloc(sizeof(*e));
5506+ if (e == NULL)
5507+ return NULL;
5508+ mbedtls_ecp_group_init(e);
5509+ if (mbedtls_ecp_group_load(e, grp_id) == 0)
5510+ return (struct crypto_ec *)e;
5511+
5512+ mbedtls_ecp_group_free(e);
5513+ os_free(e);
5514+ return NULL;
5515+}
5516+
5517+void crypto_ec_deinit(struct crypto_ec *e)
5518+{
5519+ mbedtls_ecp_group_free((mbedtls_ecp_group *)e);
5520+ os_free(e);
5521+}
5522+
5523+size_t crypto_ec_prime_len(struct crypto_ec *e)
5524+{
5525+ return CRYPTO_EC_plen(e);
5526+}
5527+
5528+size_t crypto_ec_prime_len_bits(struct crypto_ec *e)
5529+{
5530+ return CRYPTO_EC_pbits(e);
5531+}
5532+
5533+size_t crypto_ec_order_len(struct crypto_ec *e)
5534+{
5535+ return (mbedtls_mpi_bitlen(CRYPTO_EC_N(e)) + 7) / 8;
5536+}
5537+
5538+const struct crypto_bignum *crypto_ec_get_prime(struct crypto_ec *e)
5539+{
5540+ return (const struct crypto_bignum *)CRYPTO_EC_P(e);
5541+}
5542+
5543+const struct crypto_bignum *crypto_ec_get_order(struct crypto_ec *e)
5544+{
5545+ return (const struct crypto_bignum *)CRYPTO_EC_N(e);
5546+}
5547+
5548+const struct crypto_bignum *crypto_ec_get_a(struct crypto_ec *e)
5549+{
5550+ static const uint8_t secp256r1_a[] =
5551+ {0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x01,
5552+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
5553+ 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,
5554+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc};
5555+ static const uint8_t secp384r1_a[] =
5556+ {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
5557+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
5558+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
5559+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,
5560+ 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,
5561+ 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xfc};
5562+ static const uint8_t secp521r1_a[] =
5563+ {0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
5564+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
5565+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
5566+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
5567+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
5568+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
5569+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
5570+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
5571+ 0xff,0xfc};
5572+ static const uint8_t secp192r1_a[] =
5573+ {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
5574+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,
5575+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc};
5576+ static const uint8_t secp224r1_a[] =
5577+ {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
5578+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,
5579+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
5580+ 0xff,0xff,0xff,0xfe};
5581+
5582+ const uint8_t *bin = NULL;
5583+ size_t len = 0;
5584+
5585+ /* (mbedtls groups matching supported sswu_curve_param() IKE groups) */
5586+ switch (((mbedtls_ecp_group *)e)->id) {
5587+ #ifdef MBEDTLS_ECP_DP_SECP256R1_ENABLED
5588+ case MBEDTLS_ECP_DP_SECP256R1:
5589+ bin = secp256r1_a;
5590+ len = sizeof(secp256r1_a);
5591+ break;
5592+ #endif
5593+ #ifdef MBEDTLS_ECP_DP_SECP384R1_ENABLED
5594+ case MBEDTLS_ECP_DP_SECP384R1:
5595+ bin = secp384r1_a;
5596+ len = sizeof(secp384r1_a);
5597+ break;
5598+ #endif
5599+ #ifdef MBEDTLS_ECP_DP_SECP521R1_ENABLED
5600+ case MBEDTLS_ECP_DP_SECP521R1:
5601+ bin = secp521r1_a;
5602+ len = sizeof(secp521r1_a);
5603+ break;
5604+ #endif
5605+ #ifdef MBEDTLS_ECP_DP_SECP192R1_ENABLED
5606+ case MBEDTLS_ECP_DP_SECP192R1:
5607+ bin = secp192r1_a;
5608+ len = sizeof(secp192r1_a);
5609+ break;
5610+ #endif
5611+ #ifdef MBEDTLS_ECP_DP_SECP224R1_ENABLED
5612+ case MBEDTLS_ECP_DP_SECP224R1:
5613+ bin = secp224r1_a;
5614+ len = sizeof(secp224r1_a);
5615+ break;
5616+ #endif
5617+ #ifdef MBEDTLS_ECP_DP_BP256R1_ENABLED
5618+ case MBEDTLS_ECP_DP_BP256R1:
5619+ return (const struct crypto_bignum *)CRYPTO_EC_A(e);
5620+ #endif
5621+ #ifdef MBEDTLS_ECP_DP_BP384R1_ENABLED
5622+ case MBEDTLS_ECP_DP_BP384R1:
5623+ return (const struct crypto_bignum *)CRYPTO_EC_A(e);
5624+ #endif
5625+ #ifdef MBEDTLS_ECP_DP_BP512R1_ENABLED
5626+ case MBEDTLS_ECP_DP_BP512R1:
5627+ return (const struct crypto_bignum *)CRYPTO_EC_A(e);
5628+ #endif
5629+ #ifdef MBEDTLS_ECP_DP_CURVE25519_ENABLED
5630+ case MBEDTLS_ECP_DP_CURVE25519:
5631+ return (const struct crypto_bignum *)CRYPTO_EC_A(e);
5632+ #endif
5633+ #ifdef MBEDTLS_ECP_DP_CURVE448_ENABLED
5634+ case MBEDTLS_ECP_DP_CURVE448:
5635+ return (const struct crypto_bignum *)CRYPTO_EC_A(e);
5636+ #endif
5637+ default:
5638+ return NULL;
5639+ }
5640+
5641+ /*(note: not thread-safe; returns file-scoped static storage)*/
5642+ if (mbedtls_mpi_read_binary(&mpi_sw_A, bin, len) == 0)
5643+ return (const struct crypto_bignum *)&mpi_sw_A;
5644+ return NULL;
5645+}
5646+
5647+const struct crypto_bignum *crypto_ec_get_b(struct crypto_ec *e)
5648+{
5649+ return (const struct crypto_bignum *)CRYPTO_EC_B(e);
5650+}
5651+
5652+const struct crypto_ec_point * crypto_ec_get_generator(struct crypto_ec *e)
5653+{
5654+ return (const struct crypto_ec_point *)CRYPTO_EC_G(e);
5655+}
5656+
5657+struct crypto_ec_point *crypto_ec_point_init(struct crypto_ec *e)
5658+{
5659+ if (TEST_FAIL())
5660+ return NULL;
5661+
5662+ mbedtls_ecp_point *p = os_malloc(sizeof(*p));
5663+ if (p != NULL)
5664+ mbedtls_ecp_point_init(p);
5665+ return (struct crypto_ec_point *)p;
5666+}
5667+
5668+void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear)
5669+{
5670+ mbedtls_ecp_point_free((mbedtls_ecp_point *)p);
5671+ os_free(p);
5672+}
5673+
5674+int crypto_ec_point_x(struct crypto_ec *e, const struct crypto_ec_point *p,
5675+ struct crypto_bignum *x)
5676+{
5677+ mbedtls_mpi *px = &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(X);
5678+ return mbedtls_mpi_copy((mbedtls_mpi *)x, px)
5679+ ? -1
5680+ : 0;
5681+}
5682+
5683+int crypto_ec_point_to_bin(struct crypto_ec *e,
5684+ const struct crypto_ec_point *point, u8 *x, u8 *y)
5685+{
5686+ if (TEST_FAIL())
5687+ return -1;
5688+
5689+ /* crypto.h documents crypto_ec_point_to_bin() output is big-endian */
5690+ size_t len = CRYPTO_EC_plen(e);
5691+ if (x) {
5692+ mbedtls_mpi *px = &((mbedtls_ecp_point *)point)->MBEDTLS_PRIVATE(X);
5693+ if (mbedtls_mpi_write_binary(px, x, len))
5694+ return -1;
5695+ }
5696+ if (y) {
5697+ #if 0 /*(should not be necessary; py mpi should be in initial state)*/
5698+ #ifdef MBEDTLS_ECP_MONTGOMERY_ENABLED
5699+ if (mbedtls_ecp_get_type((mbedtls_ecp_group *)e)
5700+ == MBEDTLS_ECP_TYPE_MONTGOMERY) {
5701+ os_memset(y, 0, len);
5702+ return 0;
5703+ }
5704+ #endif
5705+ #endif
5706+ mbedtls_mpi *py = &((mbedtls_ecp_point *)point)->MBEDTLS_PRIVATE(Y);
5707+ if (mbedtls_mpi_write_binary(py, y, len))
5708+ return -1;
5709+ }
5710+ return 0;
5711+}
5712+
5713+struct crypto_ec_point * crypto_ec_point_from_bin(struct crypto_ec *e,
5714+ const u8 *val)
5715+{
5716+ if (TEST_FAIL())
5717+ return NULL;
5718+
5719+ size_t len = CRYPTO_EC_plen(e);
5720+ mbedtls_ecp_point *p = os_malloc(sizeof(*p));
5721+ u8 buf[1+MBEDTLS_MPI_MAX_SIZE*2];
5722+ if (p == NULL)
5723+ return NULL;
5724+ mbedtls_ecp_point_init(p);
5725+
5726+ #ifdef MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED
5727+ if (mbedtls_ecp_get_type((mbedtls_ecp_group *)e)
5728+ == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {
5729+ #if 0 /* prefer alternative to MBEDTLS_PRIVATE() access */
5730+ mbedtls_mpi *px = &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(X);
5731+ mbedtls_mpi *py = &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Y);
5732+ mbedtls_mpi *pz = &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Z);
5733+
5734+ if (mbedtls_mpi_read_binary(px, val, len) == 0
5735+ && mbedtls_mpi_read_binary(py, val + len, len) == 0
5736+ && mbedtls_mpi_lset(pz, 1) == 0)
5737+ return (struct crypto_ec_point *)p;
5738+ #else
5739+ buf[0] = 0x04;
5740+ os_memcpy(buf+1, val, len*2);
5741+ if (mbedtls_ecp_point_read_binary((mbedtls_ecp_group *)e, p,
5742+ buf, 1+len*2) == 0)
5743+ return (struct crypto_ec_point *)p;
5744+ #endif
5745+ }
5746+ #endif
5747+ #ifdef MBEDTLS_ECP_MONTGOMERY_ENABLED
5748+ if (mbedtls_ecp_get_type((mbedtls_ecp_group *)e)
5749+ == MBEDTLS_ECP_TYPE_MONTGOMERY) {
5750+ /* crypto.h interface documents crypto_ec_point_from_bin()
5751+ * val is length: prime_len * 2 and is big-endian
5752+ * (Short Weierstrass is assumed by hostap)
5753+ * Reverse to little-endian format for Montgomery */
5754+ for (unsigned int i = 0; i < len; ++i)
5755+ buf[i] = val[len-1-i];
5756+ if (mbedtls_ecp_point_read_binary((mbedtls_ecp_group *)e, p,
5757+ buf, len) == 0)
5758+ return (struct crypto_ec_point *)p;
5759+ }
5760+ #endif
5761+
5762+ mbedtls_ecp_point_free(p);
5763+ os_free(p);
5764+ return NULL;
5765+}
5766+
5767+int crypto_ec_point_add(struct crypto_ec *e, const struct crypto_ec_point *a,
5768+ const struct crypto_ec_point *b,
5769+ struct crypto_ec_point *c)
5770+{
5771+ if (TEST_FAIL())
5772+ return -1;
5773+
5774+ /* mbedtls does not provide an mbedtls_ecp_point add function */
5775+ mbedtls_mpi one;
5776+ mbedtls_mpi_init(&one);
5777+ int ret = mbedtls_mpi_lset(&one, 1)
5778+ || mbedtls_ecp_muladd(
5779+ (mbedtls_ecp_group *)e, (mbedtls_ecp_point *)c,
5780+ &one, (const mbedtls_ecp_point *)a,
5781+ &one, (const mbedtls_ecp_point *)b) ? -1 : 0;
5782+ mbedtls_mpi_free(&one);
5783+ return ret;
5784+}
5785+
5786+int crypto_ec_point_mul(struct crypto_ec *e, const struct crypto_ec_point *p,
5787+ const struct crypto_bignum *b,
5788+ struct crypto_ec_point *res)
5789+{
5790+ if (TEST_FAIL())
5791+ return -1;
5792+
5793+ return mbedtls_ecp_mul(
5794+ (mbedtls_ecp_group *)e, (mbedtls_ecp_point *)res,
5795+ (const mbedtls_mpi *)b, (const mbedtls_ecp_point *)p,
5796+ mbedtls_ctr_drbg_random, crypto_mbedtls_ctr_drbg()) ? -1 : 0;
5797+}
5798+
5799+int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p)
5800+{
5801+ if (TEST_FAIL())
5802+ return -1;
5803+
5804+ if (mbedtls_ecp_get_type((mbedtls_ecp_group *)e)
5805+ == MBEDTLS_ECP_TYPE_MONTGOMERY) {
5806+ /* e.g. MBEDTLS_ECP_DP_CURVE25519 and MBEDTLS_ECP_DP_CURVE448 */
5807+ wpa_printf(MSG_ERROR,
5808+ "%s not implemented for Montgomery curves",__func__);
5809+ return -1;
5810+ }
5811+
5812+ /* mbedtls does not provide an mbedtls_ecp_point invert function */
5813+ /* below works for Short Weierstrass; incorrect for Montgomery curves */
5814+ mbedtls_mpi *py = &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Y);
5815+ return mbedtls_ecp_is_zero((mbedtls_ecp_point *)p) /*point at infinity*/
5816+ || mbedtls_mpi_cmp_int(py, 0) == 0 /*point is its own inverse*/
5817+ || mbedtls_mpi_sub_abs(py, CRYPTO_EC_P(e), py) == 0 ? 0 : -1;
5818+}
5819+
5820+#ifdef MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED
5821+static int
5822+crypto_ec_point_y_sqr_weierstrass(mbedtls_ecp_group *e, const mbedtls_mpi *x,
5823+ mbedtls_mpi *y2)
5824+{
5825+ /* MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS y^2 = x^3 + a x + b */
5826+
5827+ /* Short Weierstrass elliptic curve group w/o A set treated as A = -3 */
5828+ /* Attempt to match mbedtls/library/ecp.c:ecp_check_pubkey_sw() behavior
5829+ * and elsewhere in mbedtls/library/ecp.c where if A is not set, it is
5830+ * treated as if A = -3. */
5831+
5832+ #if 0
5833+ /* y^2 = x^3 + ax + b */
5834+ mbedtls_mpi *A = &e->A;
5835+ mbedtls_mpi t, A_neg3;
5836+ if (&e->A.p == NULL) {
5837+ mbedtls_mpi_init(&A_neg3);
5838+ if (mbedtls_mpi_lset(&A_neg3, -3) != 0) {
5839+ mbedtls_mpi_free(&A_neg3);
5840+ return -1;
5841+ }
5842+ A = &A_neg3;
5843+ }
5844+ mbedtls_mpi_init(&t);
5845+ int ret = /* x^3 */
5846+ mbedtls_mpi_lset(&t, 3)
5847+ || mbedtls_mpi_exp_mod(y2, x, &t, &e->P, NULL)
5848+ /* ax */
5849+ || mbedtls_mpi_mul_mpi(y2, y2, A)
5850+ || mbedtls_mpi_mod_mpi(&t, &t, &e->P)
5851+ /* ax + b */
5852+ || mbedtls_mpi_add_mpi(&t, &t, &e->B)
5853+ || mbedtls_mpi_mod_mpi(&t, &t, &e->P)
5854+ /* x^3 + ax + b */
5855+ || mbedtls_mpi_add_mpi(&t, &t, y2) /* ax + b + x^3 */
5856+ || mbedtls_mpi_mod_mpi(y2, &t, &e->P);
5857+ mbedtls_mpi_free(&t);
5858+ if (A == &A_neg3)
5859+ mbedtls_mpi_free(&A_neg3);
5860+ return ret; /* 0: success, non-zero: failure */
5861+ #else
5862+ /* y^2 = x^3 + ax + b = (x^2 + a)x + b */
5863+ return /* x^2 */
5864+ mbedtls_mpi_mul_mpi(y2, x, x)
5865+ || mbedtls_mpi_mod_mpi(y2, y2, &e->P)
5866+ /* x^2 + a */
5867+ || (e->A.MBEDTLS_PRIVATE(p)
5868+ ? mbedtls_mpi_add_mpi(y2, y2, &e->A)
5869+ : mbedtls_mpi_sub_int(y2, y2, 3))
5870+ || mbedtls_mpi_mod_mpi(y2, y2, &e->P)
5871+ /* (x^2 + a)x */
5872+ || mbedtls_mpi_mul_mpi(y2, y2, x)
5873+ || mbedtls_mpi_mod_mpi(y2, y2, &e->P)
5874+ /* (x^2 + a)x + b */
5875+ || mbedtls_mpi_add_mpi(y2, y2, &e->B)
5876+ || mbedtls_mpi_mod_mpi(y2, y2, &e->P);
5877+ #endif
5878+}
5879+#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */
5880+
5881+#if 0 /* not used by hostap */
5882+#ifdef MBEDTLS_ECP_MONTGOMERY_ENABLED
5883+static int
5884+crypto_ec_point_y_sqr_montgomery(mbedtls_ecp_group *e, const mbedtls_mpi *x,
5885+ mbedtls_mpi *y2)
5886+{
5887+ /* XXX: !!! must be reviewed and audited for correctness !!! */
5888+
5889+ /* MBEDTLS_ECP_TYPE_MONTGOMERY y^2 = x^3 + a x^2 + x */
5890+
5891+ /* y^2 = x^3 + a x^2 + x = (x + a)x^2 + x */
5892+ mbedtls_mpi x2;
5893+ mbedtls_mpi_init(&x2);
5894+ int ret = /* x^2 */
5895+ mbedtls_mpi_mul_mpi(&x2, x, x)
5896+ || mbedtls_mpi_mod_mpi(&x2, &x2, &e->P)
5897+ /* x + a */
5898+ || mbedtls_mpi_add_mpi(y2, x, &e->A)
5899+ || mbedtls_mpi_mod_mpi(y2, y2, &e->P)
5900+ /* (x + a)x^2 */
5901+ || mbedtls_mpi_mul_mpi(y2, y2, &x2)
5902+ || mbedtls_mpi_mod_mpi(y2, y2, &e->P)
5903+ /* (x + a)x^2 + x */
5904+ || mbedtls_mpi_add_mpi(y2, y2, x)
5905+ || mbedtls_mpi_mod_mpi(y2, y2, &e->P);
5906+ mbedtls_mpi_free(&x2);
5907+ return ret; /* 0: success, non-zero: failure */
5908+}
5909+#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */
5910+#endif
5911+
5912+struct crypto_bignum *
5913+crypto_ec_point_compute_y_sqr(struct crypto_ec *e,
5914+ const struct crypto_bignum *x)
5915+{
5916+ if (TEST_FAIL())
5917+ return NULL;
5918+
5919+ mbedtls_mpi *y2 = os_malloc(sizeof(*y2));
5920+ if (y2 == NULL)
5921+ return NULL;
5922+ mbedtls_mpi_init(y2);
5923+
5924+ #ifdef MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED
5925+ if (mbedtls_ecp_get_type((mbedtls_ecp_group *)e)
5926+ == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS
5927+ && crypto_ec_point_y_sqr_weierstrass((mbedtls_ecp_group *)e,
5928+ (const mbedtls_mpi *)x,
5929+ y2) == 0)
5930+ return (struct crypto_bignum *)y2;
5931+ #endif
5932+ #if 0 /* not used by hostap */
5933+ #ifdef MBEDTLS_ECP_MONTGOMERY_ENABLED
5934+ if (mbedtls_ecp_get_type((mbedtls_ecp_group *)e)
5935+ == MBEDTLS_ECP_TYPE_MONTGOMERY
5936+ && crypto_ec_point_y_sqr_montgomery((mbedtls_ecp_group *)e,
5937+ (const mbedtls_mpi *)x,
5938+ y2) == 0)
5939+ return (struct crypto_bignum *)y2;
5940+ #endif
5941+ #endif
5942+
5943+ mbedtls_mpi_free(y2);
5944+ os_free(y2);
5945+ return NULL;
5946+}
5947+
5948+int crypto_ec_point_is_at_infinity(struct crypto_ec *e,
5949+ const struct crypto_ec_point *p)
5950+{
5951+ return mbedtls_ecp_is_zero((mbedtls_ecp_point *)p);
5952+}
5953+
5954+int crypto_ec_point_is_on_curve(struct crypto_ec *e,
5955+ const struct crypto_ec_point *p)
5956+{
5957+ #if 1
5958+ return mbedtls_ecp_check_pubkey((const mbedtls_ecp_group *)e,
5959+ (const mbedtls_ecp_point *)p) == 0;
5960+ #else
5961+ /* compute y^2 mod P and compare to y^2 mod P */
5962+ /*(ref: src/eap_common/eap_pwd_common.c:compute_password_element())*/
5963+ const mbedtls_mpi *px = &((const mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(X);
5964+ mbedtls_mpi *cy2 = (mbedtls_mpi *)
5965+ crypto_ec_point_compute_y_sqr(e, (const struct crypto_bignum *)px);
5966+ if (cy2 == NULL)
5967+ return 0;
5968+
5969+ mbedtls_mpi y2;
5970+ mbedtls_mpi_init(&y2);
5971+ const mbedtls_mpi *py = &((const mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Y);
5972+ int is_on_curve = mbedtls_mpi_mul_mpi(&y2, py, py) /* y^2 mod P */
5973+ || mbedtls_mpi_mod_mpi(&y2, &y2, CRYPTO_EC_P(e))
5974+ || mbedtls_mpi_cmp_mpi(&y2, cy2) != 0 ? 0 : 1;
5975+
5976+ mbedtls_mpi_free(&y2);
5977+ mbedtls_mpi_free(cy2);
5978+ os_free(cy2);
5979+ return is_on_curve;
5980+ #endif
5981+}
5982+
5983+int crypto_ec_point_cmp(const struct crypto_ec *e,
5984+ const struct crypto_ec_point *a,
5985+ const struct crypto_ec_point *b)
5986+{
5987+ return mbedtls_ecp_point_cmp((const mbedtls_ecp_point *)a,
5988+ (const mbedtls_ecp_point *)b);
5989+}
5990+
5991+#if !defined(CONFIG_NO_STDOUT_DEBUG)
5992+void crypto_ec_point_debug_print(const struct crypto_ec *e,
5993+ const struct crypto_ec_point *p,
5994+ const char *title)
5995+{
5996+ u8 x[MBEDTLS_MPI_MAX_SIZE];
5997+ u8 y[MBEDTLS_MPI_MAX_SIZE];
5998+ size_t len = CRYPTO_EC_plen(e);
5999+ /* crypto_ec_point_to_bin ought to take (const struct crypto_ec *e) */
6000+ struct crypto_ec *ee;
6001+ *(const struct crypto_ec **)&ee = e; /*(cast away const)*/
6002+ if (crypto_ec_point_to_bin(ee, p, x, y) == 0) {
6003+ if (title)
6004+ wpa_printf(MSG_DEBUG, "%s", title);
6005+ wpa_hexdump(MSG_DEBUG, "x:", x, len);
6006+ wpa_hexdump(MSG_DEBUG, "y:", y, len);
6007+ }
6008+}
6009+#endif
6010+
6011+
6012+struct crypto_ec_key * crypto_ec_key_parse_priv(const u8 *der, size_t der_len)
6013+{
6014+ mbedtls_pk_context *ctx = os_malloc(sizeof(*ctx));
6015+ if (ctx == NULL)
6016+ return NULL;
6017+ mbedtls_pk_init(ctx);
6018+ #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */
6019+ if (mbedtls_pk_parse_key(ctx, der, der_len, NULL, 0) == 0)
6020+ #else
6021+ if (mbedtls_pk_parse_key(ctx, der, der_len, NULL, 0,
6022+ mbedtls_ctr_drbg_random,
6023+ crypto_mbedtls_ctr_drbg()) == 0)
6024+ #endif
6025+ return (struct crypto_ec_key *)ctx;
6026+
6027+ mbedtls_pk_free(ctx);
6028+ os_free(ctx);
6029+ return NULL;
6030+}
6031+
6032+#ifdef CRYPTO_MBEDTLS_CRYPTO_HPKE
6033+#ifdef CONFIG_MODULE_TESTS
6034+/*(for crypto_module_tests.c)*/
6035+struct crypto_ec_key * crypto_ec_key_set_priv(int group,
6036+ const u8 *raw, size_t raw_len)
6037+{
6038+ mbedtls_ecp_group_id grp_id =
6039+ crypto_mbedtls_ecp_group_id_from_ike_id(group);
6040+ if (grp_id == MBEDTLS_ECP_DP_NONE)
6041+ return NULL;
6042+ const mbedtls_pk_info_t *pk_info =
6043+ mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
6044+ if (pk_info == NULL)
6045+ return NULL;
6046+ mbedtls_pk_context *ctx = os_malloc(sizeof(*ctx));
6047+ if (ctx == NULL)
6048+ return NULL;
6049+ mbedtls_pk_init(ctx);
6050+ if (mbedtls_pk_setup(ctx, pk_info) == 0
6051+ && mbedtls_ecp_read_key(grp_id,mbedtls_pk_ec(*ctx),raw,raw_len) == 0) {
6052+ return (struct crypto_ec_key *)ctx;
6053+ }
6054+
6055+ mbedtls_pk_free(ctx);
6056+ os_free(ctx);
6057+ return NULL;
6058+}
6059+#endif
6060+#endif
6061+
6062+#include <mbedtls/error.h>
6063+#include <mbedtls/oid.h>
6064+static int crypto_mbedtls_pk_parse_subpubkey_compressed(mbedtls_pk_context *ctx, const u8 *der, size_t der_len)
6065+{
6066+ /* The following is modified from:
6067+ * mbedtls/library/pkparse.c:mbedtls_pk_parse_subpubkey()
6068+ * mbedtls/library/pkparse.c:pk_get_pk_alg()
6069+ * mbedtls/library/pkparse.c:pk_use_ecparams()
6070+ */
6071+ mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
6072+ const mbedtls_pk_info_t *pk_info;
6073+ int ret;
6074+ size_t len;
6075+ const unsigned char *end = der+der_len;
6076+ unsigned char *p;
6077+ *(const unsigned char **)&p = der;
6078+
6079+ if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
6080+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
6081+ {
6082+ return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
6083+ }
6084+
6085+ end = p + len;
6086+
6087+ /*
6088+ if( ( ret = pk_get_pk_alg( &p, end, &pk_alg, &alg_params ) ) != 0 )
6089+ return( ret );
6090+ */
6091+ mbedtls_asn1_buf alg_oid, params;
6092+ memset( &params, 0, sizeof(mbedtls_asn1_buf) );
6093+ if( ( ret = mbedtls_asn1_get_alg( &p, end, &alg_oid, &params ) ) != 0 )
6094+ return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_ALG, ret ) );
6095+ if( mbedtls_oid_get_pk_alg( &alg_oid, &pk_alg ) != 0 )
6096+ return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
6097+
6098+ if( ( ret = mbedtls_asn1_get_bitstring_null( &p, end, &len ) ) != 0 )
6099+ return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, ret ) );
6100+
6101+ if( p + len != end )
6102+ return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY,
6103+ MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
6104+
6105+ if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL )
6106+ return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
6107+
6108+ if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 )
6109+ return( ret );
6110+
6111+ /* assume mbedtls_pk_parse_subpubkey(&der, der+der_len, ctx)
6112+ * has already run with ctx initialized up to pk_get_ecpubkey(),
6113+ * and pk_get_ecpubkey() has returned MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
6114+ *
6115+ * mbedtls mbedtls_ecp_point_read_binary()
6116+ * does not handle point in COMPRESSED format
6117+ *
6118+ * (validate assumption that algorithm is EC) */
6119+ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*ctx);
6120+ if (ecp_kp == NULL)
6121+ return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
6122+ mbedtls_ecp_group *ecp_kp_grp = &ecp_kp->MBEDTLS_PRIVATE(grp);
6123+ mbedtls_ecp_point *ecp_kp_Q = &ecp_kp->MBEDTLS_PRIVATE(Q);
6124+ mbedtls_ecp_group_id grp_id;
6125+
6126+
6127+ /* mbedtls/library/pkparse.c:pk_use_ecparams() */
6128+
6129+ if( params.tag == MBEDTLS_ASN1_OID )
6130+ {
6131+ if( mbedtls_oid_get_ec_grp( &params, &grp_id ) != 0 )
6132+ return( MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE );
6133+ }
6134+ else
6135+ {
6136+#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED)
6137+ /*(large code block not copied from mbedtls; unsupported)*/
6138+ #if 0
6139+ if( ( ret = pk_group_id_from_specified( &params, &grp_id ) ) != 0 )
6140+ return( ret );
6141+ #endif
6142+#endif
6143+ return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
6144+ }
6145+
6146+ /*
6147+ * grp may already be initialized; if so, make sure IDs match
6148+ */
6149+ if( ecp_kp_grp->id != MBEDTLS_ECP_DP_NONE && ecp_kp_grp->id != grp_id )
6150+ return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
6151+
6152+ if( ( ret = mbedtls_ecp_group_load( ecp_kp_grp, grp_id ) ) != 0 )
6153+ return( ret );
6154+
6155+
6156+ /* (validate assumption that EC point is in COMPRESSED format) */
6157+ len = CRYPTO_EC_plen(ecp_kp_grp);
6158+ if( mbedtls_ecp_get_type(ecp_kp_grp) != MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS
6159+ || (end - p) != 1+len
6160+ || (*p != 0x02 && *p != 0x03) )
6161+ return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
6162+
6163+ /* Instead of calling mbedtls/library/pkparse.c:pk_get_ecpubkey() to call
6164+ * mbedtls_ecp_point_read_binary(), manually parse point into ecp_kp_Q */
6165+ mbedtls_mpi *X = &ecp_kp_Q->MBEDTLS_PRIVATE(X);
6166+ mbedtls_mpi *Y = &ecp_kp_Q->MBEDTLS_PRIVATE(Y);
6167+ mbedtls_mpi *Z = &ecp_kp_Q->MBEDTLS_PRIVATE(Z);
6168+ ret = mbedtls_mpi_lset(Z, 1);
6169+ if (ret != 0)
6170+ return( ret );
6171+ ret = mbedtls_mpi_read_binary(X, p+1, len);
6172+ if (ret != 0)
6173+ return( ret );
6174+ /* derive Y
6175+ * (similar derivation of Y in crypto_mbedtls.c:crypto_ecdh_set_peerkey())*/
6176+ ret = mbedtls_mpi_copy(Y, X) /*(Y is used as input and output obj below)*/
6177+ || crypto_mbedtls_short_weierstrass_derive_y(ecp_kp_grp, Y, (*p & 1));
6178+ if (ret != 0)
6179+ return( ret );
6180+
6181+ return mbedtls_ecp_check_pubkey( ecp_kp_grp, ecp_kp_Q );
6182+}
6183+
6184+struct crypto_ec_key * crypto_ec_key_parse_pub(const u8 *der, size_t der_len)
6185+{
6186+ mbedtls_pk_context *ctx = os_malloc(sizeof(*ctx));
6187+ if (ctx == NULL)
6188+ return NULL;
6189+ mbedtls_pk_init(ctx);
6190+ /*int rc = mbedtls_pk_parse_subpubkey(&der, der+der_len, ctx);*/
6191+ int rc = mbedtls_pk_parse_public_key(ctx, der, der_len);
6192+ if (rc == 0)
6193+ return (struct crypto_ec_key *)ctx;
6194+ else if (rc == MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) {
6195+ /* mbedtls mbedtls_ecp_point_read_binary()
6196+ * does not handle point in COMPRESSED format; parse internally */
6197+ rc = crypto_mbedtls_pk_parse_subpubkey_compressed(ctx,der,der_len);
6198+ if (rc == 0)
6199+ return (struct crypto_ec_key *)ctx;
6200+ }
6201+
6202+ mbedtls_pk_free(ctx);
6203+ os_free(ctx);
6204+ return NULL;
6205+}
6206+
6207+#ifdef CRYPTO_MBEDTLS_CRYPTO_EC_DPP
6208+
6209+static struct crypto_ec_key *
6210+crypto_ec_key_set_pub_point_for_group(mbedtls_ecp_group_id grp_id,
6211+ const mbedtls_ecp_point *pub,
6212+ const u8 *buf, size_t len)
6213+{
6214+ const mbedtls_pk_info_t *pk_info =
6215+ mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
6216+ if (pk_info == NULL)
6217+ return NULL;
6218+ mbedtls_pk_context *ctx = os_malloc(sizeof(*ctx));
6219+ if (ctx == NULL)
6220+ return NULL;
6221+ mbedtls_pk_init(ctx);
6222+ if (mbedtls_pk_setup(ctx, pk_info) == 0) {
6223+ /* (Is private key generation necessary for callers?)
6224+ * alt: gen key then overwrite Q
6225+ * mbedtls_ecp_gen_key(grp_id, ecp_kp,
6226+ * mbedtls_ctr_drbg_random,
6227+ * crypto_mbedtls_ctr_drbg()) == 0
6228+ */
6229+ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*ctx);
6230+ mbedtls_ecp_group *ecp_kp_grp = &ecp_kp->MBEDTLS_PRIVATE(grp);
6231+ mbedtls_ecp_point *ecp_kp_Q = &ecp_kp->MBEDTLS_PRIVATE(Q);
6232+ mbedtls_mpi *ecp_kp_d = &ecp_kp->MBEDTLS_PRIVATE(d);
6233+ if (mbedtls_ecp_group_load(ecp_kp_grp, grp_id) == 0
6234+ && (pub
6235+ ? mbedtls_ecp_copy(ecp_kp_Q, pub) == 0
6236+ : mbedtls_ecp_point_read_binary(ecp_kp_grp, ecp_kp_Q,
6237+ buf, len) == 0)
6238+ && mbedtls_ecp_gen_privkey(ecp_kp_grp, ecp_kp_d,
6239+ mbedtls_ctr_drbg_random,
6240+ crypto_mbedtls_ctr_drbg()) == 0){
6241+ return (struct crypto_ec_key *)ctx;
6242+ }
6243+ }
6244+
6245+ mbedtls_pk_free(ctx);
6246+ os_free(ctx);
6247+ return NULL;
6248+}
6249+
6250+struct crypto_ec_key * crypto_ec_key_set_pub(int group, const u8 *x,
6251+ const u8 *y, size_t len)
6252+{
6253+ mbedtls_ecp_group_id grp_id =
6254+ crypto_mbedtls_ecp_group_id_from_ike_id(group);
6255+ if (grp_id == MBEDTLS_ECP_DP_NONE)
6256+ return NULL;
6257+ if (len > MBEDTLS_MPI_MAX_SIZE)
6258+ return NULL;
6259+ u8 buf[1+MBEDTLS_MPI_MAX_SIZE*2];
6260+ buf[0] = 0x04; /* assume x,y for Short Weierstrass */
6261+ os_memcpy(buf+1, x, len);
6262+ os_memcpy(buf+1+len, y, len);
6263+
6264+ return crypto_ec_key_set_pub_point_for_group(grp_id,NULL,buf,1+len*2);
6265+}
6266+
6267+struct crypto_ec_key *
6268+crypto_ec_key_set_pub_point(struct crypto_ec *e,
6269+ const struct crypto_ec_point *pub)
6270+{
6271+ mbedtls_ecp_group_id grp_id = ((mbedtls_ecp_group *)e)->id;
6272+ mbedtls_ecp_point *p = (mbedtls_ecp_point *)pub;
6273+ return crypto_ec_key_set_pub_point_for_group(grp_id, p, NULL, 0);
6274+}
6275+
6276+
6277+struct crypto_ec_key * crypto_ec_key_gen(int group)
6278+{
6279+ mbedtls_pk_context *ctx = os_malloc(sizeof(*ctx));
6280+ if (ctx == NULL)
6281+ return NULL;
6282+ mbedtls_pk_init(ctx);
6283+ if (crypto_mbedtls_keypair_gen(group, ctx) == 0)
6284+ return (struct crypto_ec_key *)ctx;
6285+ mbedtls_pk_free(ctx);
6286+ os_free(ctx);
6287+ return NULL;
6288+}
6289+
6290+#endif /* CRYPTO_MBEDTLS_CRYPTO_EC_DPP */
6291+
6292+void crypto_ec_key_deinit(struct crypto_ec_key *key)
6293+{
6294+ mbedtls_pk_free((mbedtls_pk_context *)key);
6295+ os_free(key);
6296+}
6297+
6298+struct wpabuf * crypto_ec_key_get_subject_public_key(struct crypto_ec_key *key)
6299+{
6300+ /* (similar to crypto_ec_key_get_pubkey_point(),
6301+ * but compressed point format and ASN.1 DER wrapping)*/
6302+#ifndef MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES /*(mbedtls/library/pkwrite.h)*/
6303+#define MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES ( 30 + 2 * MBEDTLS_ECP_MAX_BYTES )
6304+#endif
6305+ unsigned char buf[MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES];
6306+ int len = mbedtls_pk_write_pubkey_der((mbedtls_pk_context *)key,
6307+ buf, sizeof(buf));
6308+ if (len < 0)
6309+ return NULL;
6310+ /* Note: data is written at the end of the buffer! Use the
6311+ * return value to determine where you should start
6312+ * using the buffer */
6313+ unsigned char *p = buf+sizeof(buf)-len;
6314+
6315+ #ifdef MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED
6316+ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key);
6317+ if (ecp_kp == NULL)
6318+ return NULL;
6319+ mbedtls_ecp_group *grp = &ecp_kp->MBEDTLS_PRIVATE(grp);
6320+ /* Note: sae_pk.c expects pubkey point in compressed format,
6321+ * but mbedtls_pk_write_pubkey_der() writes uncompressed format.
6322+ * Manually translate format and update lengths in DER format */
6323+ if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {
6324+ unsigned char *end = buf+sizeof(buf);
6325+ size_t n;
6326+ /* SubjectPublicKeyInfo SEQUENCE */
6327+ mbedtls_asn1_get_tag(&p, end, &n,
6328+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
6329+ /* algorithm AlgorithmIdentifier */
6330+ unsigned char *a = p;
6331+ size_t alen;
6332+ mbedtls_asn1_get_tag(&p, end, &alen,
6333+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
6334+ p += alen;
6335+ alen = (size_t)(p - a);
6336+ /* subjectPublicKey BIT STRING */
6337+ mbedtls_asn1_get_tag(&p, end, &n, MBEDTLS_ASN1_BIT_STRING);
6338+ /* rewrite into compressed point format and rebuild ASN.1 */
6339+ p[1] = (buf[sizeof(buf)-1] & 1) ? 0x03 : 0x02;
6340+ n = 1 + 1 + (n-2)/2;
6341+ len = mbedtls_asn1_write_len(&p, buf, n) + (int)n;
6342+ len += mbedtls_asn1_write_tag(&p, buf, MBEDTLS_ASN1_BIT_STRING);
6343+ os_memmove(p-alen, a, alen);
6344+ len += alen;
6345+ p -= alen;
6346+ len += mbedtls_asn1_write_len(&p, buf, (size_t)len);
6347+ len += mbedtls_asn1_write_tag(&p, buf,
6348+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
6349+ }
6350+ #endif
6351+ return wpabuf_alloc_copy(p, (size_t)len);
6352+}
6353+
6354+#ifdef CRYPTO_MBEDTLS_CRYPTO_EC_DPP
6355+
6356+struct wpabuf * crypto_ec_key_get_ecprivate_key(struct crypto_ec_key *key,
6357+ bool include_pub)
6358+{
6359+#ifndef MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES /*(mbedtls/library/pkwrite.h)*/
6360+#define MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES ( 29 + 3 * MBEDTLS_ECP_MAX_BYTES )
6361+#endif
6362+ unsigned char priv[MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES];
6363+ int privlen = mbedtls_pk_write_key_der((mbedtls_pk_context *)key,
6364+ priv, sizeof(priv));
6365+ if (privlen < 0)
6366+ return NULL;
6367+
6368+ struct wpabuf *wbuf;
6369+
6370+ /* Note: data is written at the end of the buffer! Use the
6371+ * return value to determine where you should start
6372+ * using the buffer */
6373+ /* mbedtls_pk_write_key_der() includes publicKey in DER */
6374+ if (include_pub)
6375+ wbuf = wpabuf_alloc_copy(priv+sizeof(priv)-privlen, privlen);
6376+ else {
6377+ /* calculate publicKey offset and skip from end of buffer */
6378+ unsigned char *p = priv+sizeof(priv)-privlen;
6379+ unsigned char *end = priv+sizeof(priv);
6380+ size_t len;
6381+ /* ECPrivateKey SEQUENCE */
6382+ mbedtls_asn1_get_tag(&p, end, &len,
6383+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
6384+ /* version INTEGER */
6385+ unsigned char *v = p;
6386+ mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER);
6387+ p += len;
6388+ /* privateKey OCTET STRING */
6389+ mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
6390+ p += len;
6391+ /* parameters ECParameters */
6392+ mbedtls_asn1_get_tag(&p, end, &len,
6393+ MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED);
6394+ p += len;
6395+
6396+ /* write new SEQUENCE header (we know that it fits in priv[]) */
6397+ len = (size_t)(p - v);
6398+ p = v;
6399+ len += mbedtls_asn1_write_len(&p, priv, len);
6400+ len += mbedtls_asn1_write_tag(&p, priv,
6401+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
6402+ wbuf = wpabuf_alloc_copy(p, len);
6403+ }
6404+
6405+ forced_memzero(priv, sizeof(priv));
6406+ return wbuf;
6407+}
6408+
6409+struct wpabuf * crypto_ec_key_get_pubkey_point(struct crypto_ec_key *key,
6410+ int prefix)
6411+{
6412+ /*(similarities to crypto_ecdh_get_pubkey(), but different struct)*/
6413+ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key);
6414+ if (ecp_kp == NULL)
6415+ return NULL;
6416+ mbedtls_ecp_group *grp = &ecp_kp->MBEDTLS_PRIVATE(grp);
6417+ size_t len = CRYPTO_EC_plen(grp);
6418+ #ifdef MBEDTLS_ECP_MONTGOMERY_ENABLED
6419+ /* len */
6420+ #endif
6421+ #ifdef MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED
6422+ if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS)
6423+ len = len*2+1;
6424+ #endif
6425+ struct wpabuf *buf = wpabuf_alloc(len);
6426+ if (buf == NULL)
6427+ return NULL;
6428+ mbedtls_ecp_point *ecp_kp_Q = &ecp_kp->MBEDTLS_PRIVATE(Q);
6429+ if (mbedtls_ecp_point_write_binary(grp, ecp_kp_Q,
6430+ MBEDTLS_ECP_PF_UNCOMPRESSED, &len,
6431+ wpabuf_mhead_u8(buf), len) == 0) {
6432+ if (!prefix) /* Remove 0x04 prefix if requested */
6433+ os_memmove(wpabuf_mhead(buf),wpabuf_mhead(buf)+1,--len);
6434+ wpabuf_put(buf, len);
6435+ return buf;
6436+ }
6437+
6438+ wpabuf_free(buf);
6439+ return NULL;
6440+}
6441+
6442+struct crypto_ec_point *
6443+crypto_ec_key_get_public_key(struct crypto_ec_key *key)
6444+{
6445+ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key);
6446+ if (ecp_kp == NULL)
6447+ return NULL;
6448+ mbedtls_ecp_point *p = os_malloc(sizeof(*p));
6449+ if (p != NULL) {
6450+ /*(mbedtls_ecp_export() uses &ecp_kp->MBEDTLS_PRIVATE(grp))*/
6451+ mbedtls_ecp_point_init(p);
6452+ mbedtls_ecp_point *ecp_kp_Q = &ecp_kp->MBEDTLS_PRIVATE(Q);
6453+ if (mbedtls_ecp_copy(p, ecp_kp_Q)) {
6454+ mbedtls_ecp_point_free(p);
6455+ os_free(p);
6456+ p = NULL;
6457+ }
6458+ }
6459+ return (struct crypto_ec_point *)p;
6460+}
6461+
6462+struct crypto_bignum *
6463+crypto_ec_key_get_private_key(struct crypto_ec_key *key)
6464+{
6465+ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key);
6466+ if (ecp_kp == NULL)
6467+ return NULL;
6468+ mbedtls_mpi *bn = os_malloc(sizeof(*bn));
6469+ if (bn) {
6470+ /*(mbedtls_ecp_export() uses &ecp_kp->MBEDTLS_PRIVATE(grp))*/
6471+ mbedtls_mpi_init(bn);
6472+ mbedtls_mpi *ecp_kp_d = &ecp_kp->MBEDTLS_PRIVATE(d);
6473+ if (mbedtls_mpi_copy(bn, ecp_kp_d)) {
6474+ mbedtls_mpi_free(bn);
6475+ os_free(bn);
6476+ bn = NULL;
6477+ }
6478+ }
6479+ return (struct crypto_bignum *)bn;
6480+}
6481+
6482+#endif /* CRYPTO_MBEDTLS_CRYPTO_EC_DPP */
6483+
6484+static mbedtls_md_type_t crypto_ec_key_sign_md(size_t len)
6485+{
6486+ /* get mbedtls_md_type_t from length of hash data to be signed */
6487+ switch (len) {
6488+ case 64: return MBEDTLS_MD_SHA512;
6489+ case 48: return MBEDTLS_MD_SHA384;
6490+ case 32: return MBEDTLS_MD_SHA256;
6491+ case 20: return MBEDTLS_MD_SHA1;
6492+ case 16: return MBEDTLS_MD_MD5;
6493+ default: return MBEDTLS_MD_NONE;
6494+ }
6495+}
6496+
6497+struct wpabuf * crypto_ec_key_sign(struct crypto_ec_key *key, const u8 *data,
6498+ size_t len)
6499+{
6500+ #ifndef MBEDTLS_PK_SIGNATURE_MAX_SIZE /*(defined since mbedtls 2.20.0)*/
6501+ #if MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_MPI_MAX_SIZE
6502+ #define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN
6503+ #else
6504+ #define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE
6505+ #endif
6506+ #endif
6507+ size_t sig_len = MBEDTLS_PK_SIGNATURE_MAX_SIZE;
6508+ struct wpabuf *buf = wpabuf_alloc(sig_len);
6509+ if (buf == NULL)
6510+ return NULL;
6511+ if (mbedtls_pk_sign((mbedtls_pk_context *)key,
6512+ crypto_ec_key_sign_md(len), data, len,
6513+ wpabuf_mhead_u8(buf),
6514+ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
6515+ sig_len,
6516+ #endif
6517+ &sig_len,
6518+ mbedtls_ctr_drbg_random,
6519+ crypto_mbedtls_ctr_drbg()) == 0) {
6520+ wpabuf_put(buf, sig_len);
6521+ return buf;
6522+ }
6523+
6524+ wpabuf_free(buf);
6525+ return NULL;
6526+}
6527+
6528+#ifdef CRYPTO_MBEDTLS_CRYPTO_EC_DPP
6529+struct wpabuf * crypto_ec_key_sign_r_s(struct crypto_ec_key *key,
6530+ const u8 *data, size_t len)
6531+{
6532+ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key);
6533+ if (ecp_kp == NULL)
6534+ return NULL;
6535+
6536+ size_t sig_len = MBEDTLS_ECDSA_MAX_LEN;
6537+ u8 buf[MBEDTLS_ECDSA_MAX_LEN];
6538+ if (mbedtls_ecdsa_write_signature(ecp_kp, crypto_ec_key_sign_md(len),
6539+ data, len, buf,
6540+ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
6541+ sig_len,
6542+ #endif
6543+ &sig_len,
6544+ mbedtls_ctr_drbg_random,
6545+ crypto_mbedtls_ctr_drbg())) {
6546+ return NULL;
6547+ }
6548+
6549+ /*(mbedtls_ecdsa_write_signature() writes signature in ASN.1)*/
6550+ /* parse ASN.1 to get r and s and lengths */
6551+ u8 *p = buf, *r, *s;
6552+ u8 *end = p + sig_len;
6553+ size_t rlen, slen;
6554+ mbedtls_asn1_get_tag(&p, end, &rlen,
6555+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
6556+ mbedtls_asn1_get_tag(&p, end, &rlen, MBEDTLS_ASN1_INTEGER);
6557+ r = p;
6558+ p += rlen;
6559+ mbedtls_asn1_get_tag(&p, end, &slen, MBEDTLS_ASN1_INTEGER);
6560+ s = p;
6561+
6562+ /* write raw r and s into out
6563+ * (including removal of leading 0 if added for ASN.1 integer)
6564+ * note: DPP caller expects raw r, s each padded to prime len */
6565+ mbedtls_ecp_group *ecp_kp_grp = &ecp_kp->MBEDTLS_PRIVATE(grp);
6566+ size_t plen = CRYPTO_EC_plen(ecp_kp_grp);
6567+ if (rlen > plen) {
6568+ r += (rlen - plen);
6569+ rlen = plen;
6570+ }
6571+ if (slen > plen) {
6572+ s += (slen - plen);
6573+ slen = plen;
6574+ }
6575+ struct wpabuf *out = wpabuf_alloc(plen*2);
6576+ if (out) {
6577+ wpabuf_put(out, plen*2);
6578+ p = wpabuf_mhead_u8(out);
6579+ os_memset(p, 0, plen*2);
6580+ os_memcpy(p+plen*1-rlen, r, rlen);
6581+ os_memcpy(p+plen*2-slen, s, slen);
6582+ }
6583+ return out;
6584+}
6585+#endif /* CRYPTO_MBEDTLS_CRYPTO_EC_DPP */
6586+
6587+int crypto_ec_key_verify_signature(struct crypto_ec_key *key, const u8 *data,
6588+ size_t len, const u8 *sig, size_t sig_len)
6589+{
6590+ switch (mbedtls_pk_verify((mbedtls_pk_context *)key,
6591+ crypto_ec_key_sign_md(len), data, len,
6592+ sig, sig_len)) {
6593+ case 0:
6594+ /*case MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH:*//* XXX: allow? */
6595+ return 1;
6596+ case MBEDTLS_ERR_ECP_VERIFY_FAILED:
6597+ return 0;
6598+ default:
6599+ return -1;
6600+ }
6601+}
6602+
6603+#ifdef CRYPTO_MBEDTLS_CRYPTO_EC_DPP
6604+int crypto_ec_key_verify_signature_r_s(struct crypto_ec_key *key,
6605+ const u8 *data, size_t len,
6606+ const u8 *r, size_t r_len,
6607+ const u8 *s, size_t s_len)
6608+{
6609+ /* reimplement mbedtls_ecdsa_read_signature() without encoding r and s
6610+ * into ASN.1 just for mbedtls_ecdsa_read_signature() to decode ASN.1 */
6611+ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key);
6612+ if (ecp_kp == NULL)
6613+ return -1;
6614+ mbedtls_ecp_group *ecp_kp_grp = &ecp_kp->MBEDTLS_PRIVATE(grp);
6615+ mbedtls_ecp_point *ecp_kp_Q = &ecp_kp->MBEDTLS_PRIVATE(Q);
6616+
6617+ mbedtls_mpi mpi_r;
6618+ mbedtls_mpi mpi_s;
6619+ mbedtls_mpi_init(&mpi_r);
6620+ mbedtls_mpi_init(&mpi_s);
6621+ int ret = mbedtls_mpi_read_binary(&mpi_r, r, r_len)
6622+ || mbedtls_mpi_read_binary(&mpi_s, s, s_len) ? -1 : 0;
6623+ if (ret == 0) {
6624+ ret = mbedtls_ecdsa_verify(ecp_kp_grp, data, len,
6625+ ecp_kp_Q, &mpi_r, &mpi_s);
6626+ ret = ret ? ret == MBEDTLS_ERR_ECP_BAD_INPUT_DATA ? 0 : -1 : 1;
6627+ }
6628+ mbedtls_mpi_free(&mpi_r);
6629+ mbedtls_mpi_free(&mpi_s);
6630+ return ret;
6631+}
6632+#endif /* CRYPTO_MBEDTLS_CRYPTO_EC_DPP */
6633+
6634+int crypto_ec_key_group(struct crypto_ec_key *key)
6635+{
6636+ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key);
6637+ if (ecp_kp == NULL)
6638+ return -1;
6639+ mbedtls_ecp_group *ecp_group = &ecp_kp->MBEDTLS_PRIVATE(grp);
6640+ return crypto_mbedtls_ike_id_from_ecp_group_id(ecp_group->id);
6641+}
6642+
6643+#ifdef CRYPTO_MBEDTLS_CRYPTO_EC_DPP
6644+
6645+int crypto_ec_key_cmp(struct crypto_ec_key *key1, struct crypto_ec_key *key2)
6646+{
6647+#if 0 /*(DPP is passing two public keys; unable to use pk_check_pair())*/
6648+ #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */
6649+ return mbedtls_pk_check_pair((const mbedtls_pk_context *)key1,
6650+ (const mbedtls_pk_context *)key2) ? -1 : 0;
6651+ #else
6652+ return mbedtls_pk_check_pair((const mbedtls_pk_context *)key1,
6653+ (const mbedtls_pk_context *)key2,
6654+ mbedtls_ctr_drbg_random,
6655+ crypto_mbedtls_ctr_drbg()) ? -1 : 0;
6656+ #endif
6657+#else
6658+ mbedtls_ecp_keypair *ecp_kp1=mbedtls_pk_ec(*(mbedtls_pk_context *)key1);
6659+ mbedtls_ecp_keypair *ecp_kp2=mbedtls_pk_ec(*(mbedtls_pk_context *)key2);
6660+ if (ecp_kp1 == NULL || ecp_kp2 == NULL)
6661+ return -1;
6662+ mbedtls_ecp_group *ecp_kp1_grp = &ecp_kp1->MBEDTLS_PRIVATE(grp);
6663+ mbedtls_ecp_group *ecp_kp2_grp = &ecp_kp2->MBEDTLS_PRIVATE(grp);
6664+ mbedtls_ecp_point *ecp_kp1_Q = &ecp_kp1->MBEDTLS_PRIVATE(Q);
6665+ mbedtls_ecp_point *ecp_kp2_Q = &ecp_kp2->MBEDTLS_PRIVATE(Q);
6666+ return ecp_kp1_grp->id != ecp_kp2_grp->id
6667+ || mbedtls_ecp_point_cmp(ecp_kp1_Q, ecp_kp2_Q) ? -1 : 0;
6668+#endif
6669+}
6670+
6671+void crypto_ec_key_debug_print(const struct crypto_ec_key *key,
6672+ const char *title)
6673+{
6674+ /* TBD: what info is desirable here and in what human readable format?*/
6675+ /*(crypto_openssl.c prints a human-readably public key and attributes)*/
6676+ #if 0
6677+ struct mbedtls_pk_debug_item debug_item;
6678+ if (mbedtls_pk_debug((const mbedtls_pk_context *)key, &debug_item))
6679+ return;
6680+ /* ... */
6681+ #endif
6682+ wpa_printf(MSG_DEBUG, "%s: %s not implemented", title, __func__);
6683+}
6684+
6685+#endif /* CRYPTO_MBEDTLS_CRYPTO_EC_DPP */
6686+
6687+#endif /* CRYPTO_MBEDTLS_CRYPTO_EC */
6688+
6689+
6690+#ifdef CRYPTO_MBEDTLS_CRYPTO_CSR
6691+
6692+#include <mbedtls/x509_csr.h>
6693+#include <mbedtls/oid.h>
6694+
6695+struct crypto_csr * crypto_csr_init(void)
6696+{
6697+ mbedtls_x509write_csr *csr = os_malloc(sizeof(*csr));
6698+ if (csr != NULL)
6699+ mbedtls_x509write_csr_init(csr);
6700+ return (struct crypto_csr *)csr;
6701+}
6702+
6703+struct crypto_csr * crypto_csr_verify(const struct wpabuf *req)
6704+{
6705+ /* future: look for alternatives to MBEDTLS_PRIVATE() access */
6706+
6707+ /* sole caller src/common/dpp_crypto.c:dpp_validate_csr()
6708+ * uses (mbedtls_x509_csr *) to obtain CSR_ATTR_CHALLENGE_PASSWORD
6709+ * so allocate different object (mbedtls_x509_csr *) and special-case
6710+ * object when used in crypto_csr_get_attribute() and when free()d in
6711+ * crypto_csr_deinit(). */
6712+
6713+ mbedtls_x509_csr *csr = os_malloc(sizeof(*csr));
6714+ if (csr == NULL)
6715+ return NULL;
6716+ mbedtls_x509_csr_init(csr);
6717+ const mbedtls_md_info_t *md_info;
6718+ unsigned char digest[MBEDTLS_MD_MAX_SIZE];
6719+ if (mbedtls_x509_csr_parse_der(csr,wpabuf_head(req),wpabuf_len(req))==0
6720+ && (md_info=mbedtls_md_info_from_type(csr->MBEDTLS_PRIVATE(sig_md)))
6721+ != NULL
6722+ && mbedtls_md(md_info, csr->cri.p, csr->cri.len, digest) == 0) {
6723+ switch (mbedtls_pk_verify(&csr->pk,csr->MBEDTLS_PRIVATE(sig_md),
6724+ digest, mbedtls_md_get_size(md_info),
6725+ csr->MBEDTLS_PRIVATE(sig).p,
6726+ csr->MBEDTLS_PRIVATE(sig).len)) {
6727+ case 0:
6728+ /*case MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH:*//* XXX: allow? */
6729+ return (struct crypto_csr *)((uintptr_t)csr | 1uL);
6730+ default:
6731+ break;
6732+ }
6733+ }
6734+
6735+ mbedtls_x509_csr_free(csr);
6736+ os_free(csr);
6737+ return NULL;
6738+}
6739+
6740+void crypto_csr_deinit(struct crypto_csr *csr)
6741+{
6742+ if ((uintptr_t)csr & 1uL) {
6743+ csr = (struct crypto_csr *)((uintptr_t)csr & ~1uL);
6744+ mbedtls_x509_csr_free((mbedtls_x509_csr *)csr);
6745+ }
6746+ else
6747+ mbedtls_x509write_csr_free((mbedtls_x509write_csr *)csr);
6748+ os_free(csr);
6749+}
6750+
6751+int crypto_csr_set_ec_public_key(struct crypto_csr *csr,
6752+ struct crypto_ec_key *key)
6753+{
6754+ mbedtls_x509write_csr_set_key((mbedtls_x509write_csr *)csr,
6755+ (mbedtls_pk_context *)key);
6756+ return 0;
6757+}
6758+
6759+int crypto_csr_set_name(struct crypto_csr *csr, enum crypto_csr_name type,
6760+ const char *name)
6761+{
6762+ /* specialized for src/common/dpp_crypto.c */
6763+
6764+ /* sole caller src/common/dpp_crypto.c:dpp_build_csr()
6765+ * calls this function only once, using type == CSR_NAME_CN
6766+ * (If called more than once, this code would need to append
6767+ * components to the subject name, which we could do by
6768+ * appending to (mbedtls_x509write_csr *) private member
6769+ * mbedtls_asn1_named_data *MBEDTLS_PRIVATE(subject)) */
6770+
6771+ const char *label;
6772+ switch (type) {
6773+ case CSR_NAME_CN: label = "CN="; break;
6774+ case CSR_NAME_SN: label = "SN="; break;
6775+ case CSR_NAME_C: label = "C="; break;
6776+ case CSR_NAME_O: label = "O="; break;
6777+ case CSR_NAME_OU: label = "OU="; break;
6778+ default: return -1;
6779+ }
6780+
6781+ size_t len = strlen(name);
6782+ struct wpabuf *buf = wpabuf_alloc(3+len+1);
6783+ if (buf == NULL)
6784+ return -1;
6785+ wpabuf_put_data(buf, label, strlen(label));
6786+ wpabuf_put_data(buf, name, len+1); /*(include trailing '\0')*/
6787+ /* Note: 'name' provided is set as given and should be backslash-escaped
6788+ * by caller when necessary, e.g. literal ',' which are not separating
6789+ * components should be backslash-escaped */
6790+
6791+ int ret =
6792+ mbedtls_x509write_csr_set_subject_name((mbedtls_x509write_csr *)csr,
6793+ wpabuf_head(buf)) ? -1 : 0;
6794+ wpabuf_free(buf);
6795+ return ret;
6796+}
6797+
6798+/* OBJ_pkcs9_challengePassword 1 2 840 113549 1 9 7 */
6799+static const char OBJ_pkcs9_challengePassword[] = MBEDTLS_OID_PKCS9 "\x07";
6800+
6801+int crypto_csr_set_attribute(struct crypto_csr *csr, enum crypto_csr_attr attr,
6802+ int attr_type, const u8 *value, size_t len)
6803+{
6804+ /* specialized for src/common/dpp_crypto.c */
6805+ /* sole caller src/common/dpp_crypto.c:dpp_build_csr() passes
6806+ * attr == CSR_ATTR_CHALLENGE_PASSWORD
6807+ * attr_type == ASN1_TAG_UTF8STRING */
6808+
6809+ const char *oid;
6810+ size_t oid_len;
6811+ switch (attr) {
6812+ case CSR_ATTR_CHALLENGE_PASSWORD:
6813+ oid = OBJ_pkcs9_challengePassword;
6814+ oid_len = sizeof(OBJ_pkcs9_challengePassword)-1;
6815+ break;
6816+ default:
6817+ return -1;
6818+ }
6819+
6820+ #if 0 /*(incorrect; sets an extension, not an attribute)*/
6821+ return mbedtls_x509write_csr_set_extension((mbedtls_x509write_csr *)csr,
6822+ oid, oid_len,
6823+ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
6824+ 0, /*(critical flag)*/
6825+ #endif
6826+ value, len) ? -1 : 0;
6827+ #else
6828+ (void)oid;
6829+ (void)oid_len;
6830+ #endif
6831+
6832+ /* mbedtls does not currently provide way to set an attribute in a CSR:
6833+ * https://github.com/Mbed-TLS/mbedtls/issues/4886 */
6834+ wpa_printf(MSG_ERROR,
6835+ "mbedtls does not currently support setting challengePassword "
6836+ "attribute in CSR");
6837+ return -1;
6838+}
6839+
6840+const u8 * mbedtls_x509_csr_attr_oid_value(mbedtls_x509_csr *csr,
6841+ const char *oid, size_t oid_len,
6842+ size_t *vlen, int *vtype)
6843+{
6844+ /* Note: mbedtls_x509_csr_parse_der() has parsed and validated CSR,
6845+ * so validation checks are not repeated here
6846+ *
6847+ * It would be nicer if (mbedtls_x509_csr *) had an mbedtls_x509_buf of
6848+ * Attributes (or at least a pointer) since mbedtls_x509_csr_parse_der()
6849+ * already parsed the rest of CertificationRequestInfo, some of which is
6850+ * repeated here to step to Attributes. Since csr->subject_raw.p points
6851+ * into csr->cri.p, which points into csr->raw.p, step over version and
6852+ * subject of CertificationRequestInfo (SEQUENCE) */
6853+ unsigned char *p = csr->subject_raw.p + csr->subject_raw.len;
6854+ unsigned char *end = csr->cri.p + csr->cri.len, *ext;
6855+ size_t len;
6856+
6857+ /* step over SubjectPublicKeyInfo */
6858+ mbedtls_asn1_get_tag(&p, end, &len,
6859+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
6860+ p += len;
6861+
6862+ /* Attributes
6863+ * { ATTRIBUTE:IOSet } ::= SET OF { SEQUENCE { OID, value } }
6864+ */
6865+ if (mbedtls_asn1_get_tag(&p, end, &len,
6866+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) != 0) {
6867+ return NULL;
6868+ }
6869+ while (p < end) {
6870+ if (mbedtls_asn1_get_tag(&p, end, &len,
6871+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
6872+ return NULL;
6873+ }
6874+ ext = p;
6875+ p += len;
6876+
6877+ if (mbedtls_asn1_get_tag(&ext,end,&len,MBEDTLS_ASN1_OID) != 0)
6878+ return NULL;
6879+ if (oid_len != len || 0 != memcmp(ext, oid, oid_len))
6880+ continue;
6881+
6882+ /* found oid; return value */
6883+ *vtype = *ext++; /* tag */
6884+ return (mbedtls_asn1_get_len(&ext,end,vlen) == 0) ? ext : NULL;
6885+ }
6886+
6887+ return NULL;
6888+}
6889+
6890+const u8 * crypto_csr_get_attribute(struct crypto_csr *csr,
6891+ enum crypto_csr_attr attr,
6892+ size_t *len, int *type)
6893+{
6894+ /* specialized for src/common/dpp_crypto.c */
6895+ /* sole caller src/common/dpp_crypto.c:dpp_build_csr() passes
6896+ * attr == CSR_ATTR_CHALLENGE_PASSWORD */
6897+
6898+ const char *oid;
6899+ size_t oid_len;
6900+ switch (attr) {
6901+ case CSR_ATTR_CHALLENGE_PASSWORD:
6902+ oid = OBJ_pkcs9_challengePassword;
6903+ oid_len = sizeof(OBJ_pkcs9_challengePassword)-1;
6904+ break;
6905+ default:
6906+ return NULL;
6907+ }
6908+
6909+ /* see crypto_csr_verify(); expecting (mbedtls_x509_csr *) tagged |=1 */
6910+ if (!((uintptr_t)csr & 1uL))
6911+ return NULL;
6912+ csr = (struct crypto_csr *)((uintptr_t)csr & ~1uL);
6913+
6914+ return mbedtls_x509_csr_attr_oid_value((mbedtls_x509_csr *)csr,
6915+ oid, oid_len, len, type);
6916+}
6917+
6918+struct wpabuf * crypto_csr_sign(struct crypto_csr *csr,
6919+ struct crypto_ec_key *key,
6920+ enum crypto_hash_alg algo)
6921+{
6922+ mbedtls_md_type_t sig_md;
6923+ switch (algo) {
6924+ #ifdef MBEDTLS_SHA256_C
6925+ case CRYPTO_HASH_ALG_SHA256: sig_md = MBEDTLS_MD_SHA256; break;
6926+ #endif
6927+ #ifdef MBEDTLS_SHA512_C
6928+ case CRYPTO_HASH_ALG_SHA384: sig_md = MBEDTLS_MD_SHA384; break;
6929+ case CRYPTO_HASH_ALG_SHA512: sig_md = MBEDTLS_MD_SHA512; break;
6930+ #endif
6931+ default:
6932+ return NULL;
6933+ }
6934+ mbedtls_x509write_csr_set_md_alg((mbedtls_x509write_csr *)csr, sig_md);
6935+
6936+ #if 0
6937+ unsigned char key_usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE
6938+ | MBEDTLS_X509_KU_KEY_CERT_SIGN;
6939+ if (mbedtls_x509write_csr_set_key_usage((mbedtls_x509write_csr *)csr,
6940+ key_usage))
6941+ return NULL;
6942+ #endif
6943+
6944+ #if 0
6945+ unsigned char ns_cert_type = MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT
6946+ | MBEDTLS_X509_NS_CERT_TYPE_EMAIL;
6947+ if (mbedtls_x509write_csr_set_ns_cert_type((mbedtls_x509write_csr *)csr,
6948+ ns_cert_type))
6949+ return NULL;
6950+ #endif
6951+
6952+ #if 0
6953+ /* mbedtls does not currently provide way to set an attribute in a CSR:
6954+ * https://github.com/Mbed-TLS/mbedtls/issues/4886
6955+ * XXX: hwsim dpp_enterprise test fails due to this limitation.
6956+ *
6957+ * Current usage of this function is solely by dpp_build_csr(),
6958+ * so as a kludge, might consider custom (struct crypto_csr *)
6959+ * containing (mbedtls_x509write_csr *) and a list of attributes
6960+ * (i.e. challengePassword). Might have to totally reimplement
6961+ * mbedtls_x509write_csr_der(); underlying x509write_csr_der_internal()
6962+ * handles signing the CSR. (This is more work that appending an
6963+ * Attributes section to end of CSR and adjusting ASN.1 length of CSR.)
6964+ */
6965+ #endif
6966+
6967+ unsigned char buf[4096]; /* XXX: large enough? too large? */
6968+ int len = mbedtls_x509write_csr_der((mbedtls_x509write_csr *)csr,
6969+ buf, sizeof(buf),
6970+ mbedtls_ctr_drbg_random,
6971+ crypto_mbedtls_ctr_drbg());
6972+ if (len < 0)
6973+ return NULL;
6974+ /* Note: data is written at the end of the buffer! Use the
6975+ * return value to determine where you should start
6976+ * using the buffer */
6977+ return wpabuf_alloc_copy(buf+sizeof(buf)-len, (size_t)len);
6978+}
6979+
6980+#endif /* CRYPTO_MBEDTLS_CRYPTO_CSR */
6981+
6982+
6983+#ifdef CRYPTO_MBEDTLS_CRYPTO_PKCS7
6984+
6985+#if 0
6986+#include <mbedtls/pkcs7.h> /* PKCS7 is not currently supported in mbedtls */
6987+#include <mbedtls/pem.h>
6988+#endif
6989+
6990+struct wpabuf * crypto_pkcs7_get_certificates(const struct wpabuf *pkcs7)
6991+{
6992+ /* PKCS7 is not currently supported in mbedtls */
6993+ return NULL;
6994+
6995+#if 0
6996+ /* https://github.com/naynajain/mbedtls-1 branch: development-pkcs7
6997+ * (??? potential future contribution to mbedtls ???) */
6998+
6999+ /* Note: PKCS7 signature *is not* verified by this function.
7000+ * The function interface does not provide for passing a certificate */
7001+
7002+ mbedtls_pkcs7 mpkcs7;
7003+ mbedtls_pkcs7_init(&mpkcs7);
7004+ int pkcs7_type = mbedtls_pkcs7_parse_der(wpabuf_head(pkcs7),
7005+ wpabuf_len(pkcs7),
7006+ &mpkcs7);
7007+ wpabuf *buf = NULL;
7008+ do {
7009+ if (pkcs7_type < 0)
7010+ break;
7011+
7012+ /* src/common/dpp.c:dpp_parse_cred_dot1x() interested in certs
7013+ * for wpa_supplicant/dpp_supplicant.c:wpas_dpp_add_network()
7014+ * (? are adding certificate headers and footers desired ?) */
7015+
7016+ /* development-pkcs7 branch does not currently provide
7017+ * additional interfaces to retrieve the parsed data */
7018+
7019+ mbedtls_x509_crt *certs =
7020+ &mpkcs7.MBEDTLS_PRIVATE(signed_data).MBEDTLS_PRIVATE(certs);
7021+ int ncerts =
7022+ mpkcs7.MBEDTLS_PRIVATE(signed_data).MBEDTLS_PRIVATE(no_of_certs);
7023+
7024+ /* allocate buffer for PEM (base64-encoded DER)
7025+ * plus header, footer, newlines, and some extra */
7026+ buf = wpabuf_alloc((wpabuf_len(pkcs7)+2)/3*4 + ncerts*64);
7027+ if (buf == NULL)
7028+ break;
7029+
7030+ #define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n"
7031+ #define PEM_END_CRT "-----END CERTIFICATE-----\n"
7032+ size_t olen;
7033+ for (int i = 0; i < ncerts; ++i) {
7034+ int ret = mbedtls_pem_write_buffer(
7035+ PEM_BEGIN_CRT, PEM_END_CRT,
7036+ certs[i].raw.p, certs[i].raw.len,
7037+ wpabuf_mhead(buf, 0), wpabuf_tailroom(buf),
7038+ &olen));
7039+ if (ret == 0)
7040+ wpabuf_put(buf, olen);
7041+ } else {
7042+ if (ret == MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL)
7043+ ret = wpabuf_resize(
7044+ &buf,olen-wpabuf_tailroom(buf));
7045+ if (ret == 0) {
7046+ --i;/*(adjust loop iterator for retry)*/
7047+ continue;
7048+ }
7049+ wpabuf_free(buf);
7050+ buf = NULL;
7051+ break;
7052+ }
7053+ }
7054+ } while (0);
7055+
7056+ mbedtls_pkcs7_free(&mpkcs7);
7057+ return buf;
7058+#endif
7059+}
7060+
7061+#endif /* CRYPTO_MBEDTLS_CRYPTO_PKCS7 */
7062+
7063+
7064+#ifdef MBEDTLS_ARC4_C
7065+#include <mbedtls/arc4.h>
7066+int rc4_skip(const u8 *key, size_t keylen, size_t skip,
7067+ u8 *data, size_t data_len)
7068+{
7069+ mbedtls_arc4_context ctx;
7070+ mbedtls_arc4_init(&ctx);
7071+ mbedtls_arc4_setup(&ctx, key, keylen);
7072+
7073+ if (skip) {
7074+ /*(prefer [16] on ancient hardware with smaller cache lines)*/
7075+ unsigned char skip_buf[64]; /*('skip' is generally small)*/
7076+ /*os_memset(skip_buf, 0, sizeof(skip_buf));*/ /*(necessary?)*/
7077+ size_t len;
7078+ do {
7079+ len = skip > sizeof(skip_buf) ? sizeof(skip_buf) : skip;
7080+ mbedtls_arc4_crypt(&ctx, len, skip_buf, skip_buf);
7081+ } while ((skip -= len));
7082+ }
7083+
7084+ int ret = mbedtls_arc4_crypt(&ctx, data_len, data, data);
7085+ mbedtls_arc4_free(&ctx);
7086+ return ret;
7087+}
7088+#endif
7089+
7090+
7091+/* duplicated in tls_mbedtls.c:tls_mbedtls_readfile()*/
7092+__attribute_noinline__
7093+static int crypto_mbedtls_readfile(const char *path, u8 **buf, size_t *n)
7094+{
7095+ #if 0 /* #ifdef MBEDTLS_FS_IO */
7096+ /*(includes +1 for '\0' needed by mbedtls PEM parsing funcs)*/
7097+ if (mbedtls_pk_load_file(path, (unsigned char **)buf, n) != 0) {
7098+ wpa_printf(MSG_ERROR, "error: mbedtls_pk_load_file %s", path);
7099+ return -1;
7100+ }
7101+ #else
7102+ /*(use os_readfile() so that we can use os_free()
7103+ *(if we use mbedtls_pk_load_file() above, macros prevent calling free()
7104+ * directly #if defined(OS_REJECT_C_LIB_FUNCTIONS) and calling os_free()
7105+ * on buf aborts in tests if buf not allocated via os_malloc())*/
7106+ *buf = (u8 *)os_readfile(path, n);
7107+ if (!*buf) {
7108+ wpa_printf(MSG_ERROR, "error: os_readfile %s", path);
7109+ return -1;
7110+ }
7111+ u8 *buf0 = os_realloc(*buf, *n+1);
7112+ if (!buf0) {
7113+ bin_clear_free(*buf, *n);
7114+ *buf = NULL;
7115+ return -1;
7116+ }
7117+ buf0[(*n)++] = '\0';
7118+ *buf = buf0;
7119+ #endif
7120+ return 0;
7121+}
7122+
7123+
7124+#ifdef CRYPTO_MBEDTLS_CRYPTO_RSA
7125+#ifdef MBEDTLS_RSA_C
7126+
7127+#include <mbedtls/pk.h>
7128+#include <mbedtls/rsa.h>
7129+
7130+struct crypto_rsa_key * crypto_rsa_key_read(const char *file, bool private_key)
7131+{
7132+ /* mbedtls_pk_parse_keyfile() and mbedtls_pk_parse_public_keyfile()
7133+ * require #ifdef MBEDTLS_FS_IO in mbedtls library. Prefer to use
7134+ * crypto_mbedtls_readfile(), which wraps os_readfile() */
7135+ u8 *data;
7136+ size_t len;
7137+ if (crypto_mbedtls_readfile(file, &data, &len) != 0)
7138+ return NULL;
7139+
7140+ mbedtls_pk_context *ctx = os_malloc(sizeof(*ctx));
7141+ if (ctx == NULL) {
7142+ bin_clear_free(data, len);
7143+ return NULL;
7144+ }
7145+ mbedtls_pk_init(ctx);
7146+
7147+ int rc;
7148+ rc = (private_key
7149+ ? mbedtls_pk_parse_key(ctx, data, len, NULL, 0
7150+ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
7151+ ,mbedtls_ctr_drbg_random,
7152+ crypto_mbedtls_ctr_drbg()
7153+ #endif
7154+ )
7155+ : mbedtls_pk_parse_public_key(ctx, data, len)) == 0
7156+ && mbedtls_pk_can_do(ctx, MBEDTLS_PK_RSA);
7157+
7158+ bin_clear_free(data, len);
7159+
7160+ if (rc) {
7161+ /* use MBEDTLS_RSA_PKCS_V21 padding for RSAES-OAEP */
7162+ /* use MBEDTLS_MD_SHA256 for these hostap interfaces */
7163+ #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */
7164+ /*(no return value in mbedtls 2.x)*/
7165+ mbedtls_rsa_set_padding(mbedtls_pk_rsa(*ctx),
7166+ MBEDTLS_RSA_PKCS_V21,
7167+ MBEDTLS_MD_SHA256);
7168+ #else
7169+ if (mbedtls_rsa_set_padding(mbedtls_pk_rsa(*ctx),
7170+ MBEDTLS_RSA_PKCS_V21,
7171+ MBEDTLS_MD_SHA256) == 0)
7172+ #endif
7173+ return (struct crypto_rsa_key *)ctx;
7174+ }
7175+
7176+ mbedtls_pk_free(ctx);
7177+ os_free(ctx);
7178+ return NULL;
7179+}
7180+
7181+struct wpabuf * crypto_rsa_oaep_sha256_encrypt(struct crypto_rsa_key *key,
7182+ const struct wpabuf *in)
7183+{
7184+ mbedtls_rsa_context *pk_rsa = mbedtls_pk_rsa(*(mbedtls_pk_context*)key);
7185+ size_t olen = mbedtls_rsa_get_len(pk_rsa);
7186+ struct wpabuf *buf = wpabuf_alloc(olen);
7187+ if (buf == NULL)
7188+ return NULL;
7189+
7190+ /* mbedtls_pk_encrypt() takes a few more hops to get to same func */
7191+ if (mbedtls_rsa_rsaes_oaep_encrypt(pk_rsa,
7192+ mbedtls_ctr_drbg_random,
7193+ crypto_mbedtls_ctr_drbg(),
7194+ #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */
7195+ MBEDTLS_RSA_PRIVATE,
7196+ #endif
7197+ NULL, 0,
7198+ wpabuf_len(in), wpabuf_head(in),
7199+ wpabuf_put(buf, olen)) == 0) {
7200+ return buf;
7201+ }
7202+
7203+ wpabuf_clear_free(buf);
7204+ return NULL;
7205+}
7206+
7207+struct wpabuf * crypto_rsa_oaep_sha256_decrypt(struct crypto_rsa_key *key,
7208+ const struct wpabuf *in)
7209+{
7210+ mbedtls_rsa_context *pk_rsa = mbedtls_pk_rsa(*(mbedtls_pk_context*)key);
7211+ size_t olen = mbedtls_rsa_get_len(pk_rsa);
7212+ struct wpabuf *buf = wpabuf_alloc(olen);
7213+ if (buf == NULL)
7214+ return NULL;
7215+
7216+ /* mbedtls_pk_decrypt() takes a few more hops to get to same func */
7217+ if (mbedtls_rsa_rsaes_oaep_decrypt(pk_rsa,
7218+ mbedtls_ctr_drbg_random,
7219+ crypto_mbedtls_ctr_drbg(),
7220+ #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */
7221+ MBEDTLS_RSA_PUBLIC,
7222+ #endif
7223+ NULL, 0, &olen, wpabuf_head(in),
7224+ wpabuf_mhead(buf), olen) == 0) {
7225+ wpabuf_put(buf, olen);
7226+ return buf;
7227+ }
7228+
7229+ wpabuf_clear_free(buf);
7230+ return NULL;
7231+}
7232+
7233+void crypto_rsa_key_free(struct crypto_rsa_key *key)
7234+{
7235+ mbedtls_pk_free((mbedtls_pk_context *)key);
7236+ os_free(key);
7237+}
7238+
7239+#endif /* MBEDTLS_RSA_C */
7240+#endif /* CRYPTO_MBEDTLS_CRYPTO_RSA */
7241+
7242+#ifdef CRYPTO_MBEDTLS_CRYPTO_HPKE
7243+
7244+struct wpabuf * hpke_base_seal(enum hpke_kem_id kem_id,
7245+ enum hpke_kdf_id kdf_id,
7246+ enum hpke_aead_id aead_id,
7247+ struct crypto_ec_key *peer_pub,
7248+ const u8 *info, size_t info_len,
7249+ const u8 *aad, size_t aad_len,
7250+ const u8 *pt, size_t pt_len)
7251+{
7252+ /* not yet implemented */
7253+ return NULL;
7254+}
7255+
7256+struct wpabuf * hpke_base_open(enum hpke_kem_id kem_id,
7257+ enum hpke_kdf_id kdf_id,
7258+ enum hpke_aead_id aead_id,
7259+ struct crypto_ec_key *own_priv,
7260+ const u8 *info, size_t info_len,
7261+ const u8 *aad, size_t aad_len,
7262+ const u8 *enc_ct, size_t enc_ct_len)
7263+{
7264+ /* not yet implemented */
7265+ return NULL;
7266+}
7267+
7268+#endif
7269diff --git a/src/crypto/crypto_module_tests.c b/src/crypto/crypto_module_tests.c
7270index ffeddbadd..07c36d850 100644
7271--- a/src/crypto/crypto_module_tests.c
7272+++ b/src/crypto/crypto_module_tests.c
7273@@ -2470,6 +2470,139 @@ static int test_hpke(void)
7274 }
7275
7276
7277+static int test_ecc(void)
7278+{
7279+#ifdef CONFIG_ECC
7280+#ifndef CONFIG_TLS_INTERNAL
7281+#ifndef CONFIG_TLS_GNUTLS
7282+#if defined(CONFIG_TLS_MBEDTLS) \
7283+ || defined(CONFIG_TLS_OPENSSL) \
7284+ || defined(CONFIG_TLS_WOLFSSL)
7285+ wpa_printf(MSG_INFO, "Testing ECC");
7286+ /* Note: some tests below are valid on supported Short Weierstrass
7287+ * curves, but not on Montgomery curves (e.g. IKE groups 31 and 32)
7288+ * (e.g. deriving and comparing y^2 test below not valid on Montgomery)
7289+ */
7290+#ifdef CONFIG_TLS_MBEDTLS
7291+ const int grps[] = {19, 20, 21, 25, 26, 28};
7292+#endif
7293+#ifdef CONFIG_TLS_OPENSSL
7294+ const int grps[] = {19, 20, 21, 26};
7295+#endif
7296+#ifdef CONFIG_TLS_WOLFSSL
7297+ const int grps[] = {19, 20, 21, 26};
7298+#endif
7299+ uint32_t i;
7300+ struct crypto_ec *e = NULL;
7301+ struct crypto_ec_point *p = NULL, *q = NULL;
7302+ struct crypto_bignum *x = NULL, *y = NULL;
7303+#ifdef CONFIG_DPP
7304+ u8 bin[4096];
7305+#endif
7306+ for (i = 0; i < ARRAY_SIZE(grps); ++i) {
7307+ e = crypto_ec_init(grps[i]);
7308+ if (e == NULL
7309+ || crypto_ec_prime_len(e) == 0
7310+ || crypto_ec_prime_len_bits(e) == 0
7311+ || crypto_ec_order_len(e) == 0
7312+ || crypto_ec_get_prime(e) == NULL
7313+ || crypto_ec_get_order(e) == NULL
7314+ || crypto_ec_get_a(e) == NULL
7315+ || crypto_ec_get_b(e) == NULL
7316+ || crypto_ec_get_generator(e) == NULL) {
7317+ break;
7318+ }
7319+#ifdef CONFIG_DPP
7320+ struct crypto_ec_key *key = crypto_ec_key_gen(grps[i]);
7321+ if (key == NULL)
7322+ break;
7323+ p = crypto_ec_key_get_public_key(key);
7324+ q = crypto_ec_key_get_public_key(key);
7325+ crypto_ec_key_deinit(key);
7326+ if (p == NULL || q == NULL)
7327+ break;
7328+ if (!crypto_ec_point_is_on_curve(e, p))
7329+ break;
7330+
7331+ /* inverted point should not match original;
7332+ * double-invert should match */
7333+ if (crypto_ec_point_invert(e, q) != 0
7334+ || crypto_ec_point_cmp(e, p, q) == 0
7335+ || crypto_ec_point_invert(e, q) != 0
7336+ || crypto_ec_point_cmp(e, p, q) != 0) {
7337+ break;
7338+ }
7339+
7340+ /* crypto_ec_point_to_bin() and crypto_ec_point_from_bin()
7341+ * imbalanced interfaces? */
7342+ size_t prime_len = crypto_ec_prime_len(e);
7343+ if (prime_len * 2 > sizeof(bin))
7344+ break;
7345+ if (crypto_ec_point_to_bin(e, p, bin, bin+prime_len) != 0)
7346+ break;
7347+ struct crypto_ec_point *tmp = crypto_ec_point_from_bin(e, bin);
7348+ if (tmp == NULL)
7349+ break;
7350+ if (crypto_ec_point_cmp(e, p, tmp) != 0) {
7351+ crypto_ec_point_deinit(tmp, 0);
7352+ break;
7353+ }
7354+ crypto_ec_point_deinit(tmp, 0);
7355+
7356+ x = crypto_bignum_init();
7357+ y = crypto_bignum_init_set(bin+prime_len, prime_len);
7358+ if (x == NULL || y == NULL || crypto_ec_point_x(e, p, x) != 0)
7359+ break;
7360+ struct crypto_bignum *y2 = crypto_ec_point_compute_y_sqr(e, x);
7361+ if (y2 == NULL)
7362+ break;
7363+ if (crypto_bignum_sqrmod(y, crypto_ec_get_prime(e), y) != 0
7364+ || crypto_bignum_cmp(y, y2) != 0) {
7365+ crypto_bignum_deinit(y2, 0);
7366+ break;
7367+ }
7368+ crypto_bignum_deinit(y2, 0);
7369+ crypto_bignum_deinit(x, 0);
7370+ crypto_bignum_deinit(y, 0);
7371+ x = NULL;
7372+ y = NULL;
7373+
7374+ x = crypto_bignum_init();
7375+ if (x == NULL)
7376+ break;
7377+ if (crypto_bignum_rand(x, crypto_ec_get_prime(e)) != 0)
7378+ break;
7379+ crypto_bignum_deinit(x, 0);
7380+ x = NULL;
7381+
7382+ crypto_ec_point_deinit(p, 0);
7383+ p = NULL;
7384+ crypto_ec_point_deinit(q, 0);
7385+ q = NULL;
7386+#endif /* CONFIG_DPP */
7387+ crypto_ec_deinit(e);
7388+ e = NULL;
7389+ }
7390+ if (i != ARRAY_SIZE(grps)) {
7391+ crypto_bignum_deinit(x, 0);
7392+ crypto_bignum_deinit(y, 0);
7393+ crypto_ec_point_deinit(p, 0);
7394+ crypto_ec_point_deinit(q, 0);
7395+ crypto_ec_deinit(e);
7396+ wpa_printf(MSG_INFO,
7397+ "ECC test case failed tls_id:%d", grps[i]);
7398+ return -1;
7399+ }
7400+
7401+ wpa_printf(MSG_INFO, "ECC test cases passed");
7402+#endif
7403+#endif /* !CONFIG_TLS_GNUTLS */
7404+#endif /* !CONFIG_TLS_INTERNAL */
7405+#endif /* CONFIG_ECC */
7406+ return 0;
7407+}
7408+
7409+
7410 static int test_ms_funcs(void)
7411 {
7412 #ifndef CONFIG_FIPS
7413@@ -2591,6 +2724,7 @@ int crypto_module_tests(void)
7414 test_fips186_2_prf() ||
7415 test_extract_expand_hkdf() ||
7416 test_hpke() ||
7417+ test_ecc() ||
7418 test_ms_funcs())
7419 ret = -1;
7420
developer66e89bc2024-04-23 14:50:01 +08007421diff --git a/src/crypto/tls_mbedtls.c b/src/crypto/tls_mbedtls.c
7422new file mode 100644
developer05f3b2b2024-08-19 19:17:34 +08007423index 000000000..d83a3db73
developer66e89bc2024-04-23 14:50:01 +08007424--- /dev/null
7425+++ b/src/crypto/tls_mbedtls.c
7426@@ -0,0 +1,3313 @@
7427+/*
7428+ * SSL/TLS interface functions for mbed TLS
7429+ *
7430+ * SPDX-FileCopyrightText: 2022 Glenn Strauss <gstrauss@gluelogic.com>
7431+ * SPDX-License-Identifier: BSD-3-Clause
7432+ *
7433+ * This software may be distributed under the terms of the BSD license.
7434+ * See README for more details.
7435+ *
7436+ * template: src/crypto/tls_none.c
7437+ * reference: src/crypto/tls_*.c
7438+ *
7439+ * Known Limitations:
7440+ * - no TLSv1.3 (not available in mbedtls 2.x; experimental in mbedtls 3.x)
7441+ * - no OCSP (not yet available in mbedtls)
7442+ * - mbedtls does not support all certificate encodings used by hwsim tests
7443+ * PCKS#5 v1.5
7444+ * PCKS#12
7445+ * DH DSA
7446+ * - EAP-FAST, EAP-TEAP session ticket support not implemented in tls_mbedtls.c
7447+ * - mbedtls does not currently provide way to set an attribute in a CSR
7448+ * https://github.com/Mbed-TLS/mbedtls/issues/4886
7449+ * so tests/hwsim dpp_enterprise tests fail
7450+ * - DPP2 not supported
7451+ * PKCS#7 parsing is not supported in mbedtls
7452+ * See crypto_mbedtls.c:crypto_pkcs7_get_certificates() comments
7453+ * - DPP3 not supported
7454+ * hpke_base_seal() and hpke_base_seal() not implemented in crypto_mbedtls.c
7455+ *
7456+ * Status:
7457+ * - code written to be compatible with mbedtls 2.x and mbedtls 3.x
7458+ * (currently requires mbedtls >= 2.27.0 for mbedtls_mpi_random())
7459+ * (currently requires mbedtls >= 2.18.0 for mbedtls_ssl_tls_prf())
7460+ * - builds with tests/build/build-wpa_supplicant-mbedtls.config
7461+ * - passes all tests/ crypto module tests (incomplete coverage)
7462+ * ($ cd tests; make clean; make -j 4 run-tests CONFIG_TLS=mbedtls)
7463+ * - passes almost all tests/hwsim tests
7464+ * (hwsim tests skipped for missing features)
7465+ *
7466+ * RFE:
7467+ * - EAP-FAST, EAP-TEAP session ticket support not implemented in tls_mbedtls.c
7468+ * - client/server session resumption, and/or save client session ticket
7469+ */
7470+
7471+#include "includes.h"
7472+#include "common.h"
7473+
7474+#include <mbedtls/version.h>
7475+#include <mbedtls/ctr_drbg.h>
7476+#include <mbedtls/error.h>
7477+#include <mbedtls/oid.h>
7478+#include <mbedtls/pem.h>
7479+#include <mbedtls/platform.h> /* mbedtls_calloc() mbedtls_free() */
7480+#include <mbedtls/platform_util.h> /* mbedtls_platform_zeroize() */
7481+#include <mbedtls/ssl.h>
7482+#include <mbedtls/ssl_ticket.h>
7483+#include <mbedtls/x509.h>
7484+#include <mbedtls/x509_crt.h>
7485+
7486+#if MBEDTLS_VERSION_NUMBER >= 0x02040000 /* mbedtls 2.4.0 */
7487+#include <mbedtls/net_sockets.h>
7488+#else
7489+#include <mbedtls/net.h>
7490+#endif
7491+
7492+#ifndef MBEDTLS_PRIVATE
7493+#define MBEDTLS_PRIVATE(x) x
7494+#endif
7495+
7496+#if MBEDTLS_VERSION_NUMBER < 0x03020000 /* mbedtls 3.2.0 */
7497+#define mbedtls_ssl_get_ciphersuite_id_from_ssl(ssl) \
7498+ ((ssl)->MBEDTLS_PRIVATE(session) \
7499+ ?(ssl)->MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(ciphersuite) \
7500+ : 0)
7501+#define mbedtls_ssl_ciphersuite_get_name(info) \
7502+ (info)->MBEDTLS_PRIVATE(name)
7503+#endif
7504+
7505+#include "crypto.h" /* sha256_vector() */
7506+#include "tls.h"
7507+
7508+#ifndef SHA256_DIGEST_LENGTH
7509+#define SHA256_DIGEST_LENGTH 32
7510+#endif
7511+
7512+#ifndef MBEDTLS_EXPKEY_FIXED_SECRET_LEN
7513+#define MBEDTLS_EXPKEY_FIXED_SECRET_LEN 48
7514+#endif
7515+
7516+#ifndef MBEDTLS_EXPKEY_RAND_LEN
7517+#define MBEDTLS_EXPKEY_RAND_LEN 32
7518+#endif
7519+
7520+#if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
7521+static mbedtls_ssl_export_keys_t tls_connection_export_keys_cb;
7522+#elif MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */
7523+static mbedtls_ssl_export_keys_ext_t tls_connection_export_keys_cb;
7524+#else /*(not implemented; return error)*/
7525+#define mbedtls_ssl_tls_prf(a,b,c,d,e,f,g,h) (-1)
7526+typedef mbedtls_tls_prf_types int;
7527+#endif
7528+
7529+
7530+/* hostapd/wpa_supplicant provides forced_memzero(),
7531+ * but prefer mbedtls_platform_zeroize() */
7532+#define forced_memzero(ptr,sz) mbedtls_platform_zeroize(ptr,sz)
7533+
7534+
7535+#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) \
7536+ || defined(EAP_TEAP) || defined(EAP_SERVER_TEAP)
7537+#ifdef MBEDTLS_SSL_SESSION_TICKETS
7538+#ifdef MBEDTLS_SSL_TICKET_C
7539+#define TLS_MBEDTLS_SESSION_TICKETS
7540+#if defined(EAP_TEAP) || defined(EAP_SERVER_TEAP)
7541+#define TLS_MBEDTLS_EAP_TEAP
7542+#endif
7543+#if !defined(CONFIG_FIPS) /* EAP-FAST keys cannot be exported in FIPS mode */
7544+#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST)
7545+#define TLS_MBEDTLS_EAP_FAST
7546+#endif
7547+#endif
7548+#endif
7549+#endif
7550+#endif
7551+
7552+
7553+struct tls_conf {
7554+ mbedtls_ssl_config conf;
7555+
7556+ unsigned int verify_peer:1;
7557+ unsigned int verify_depth0_only:1;
7558+ unsigned int check_crl:2; /*(needs :2 bits for 0, 1, 2)*/
7559+ unsigned int check_crl_strict:1; /*(needs :1 bit for 0, 1)*/
7560+ unsigned int ca_cert_probe:1;
7561+ unsigned int has_ca_cert:1;
7562+ unsigned int has_client_cert:1;
7563+ unsigned int has_private_key:1;
7564+ unsigned int suiteb128:1;
7565+ unsigned int suiteb192:1;
7566+ mbedtls_x509_crl *crl;
7567+ mbedtls_x509_crt ca_cert;
7568+ mbedtls_x509_crt client_cert;
7569+ mbedtls_pk_context private_key;
7570+
7571+ uint32_t refcnt;
7572+
7573+ unsigned int flags;
7574+ char *subject_match;
7575+ char *altsubject_match;
7576+ char *suffix_match;
7577+ char *domain_match;
7578+ char *check_cert_subject;
7579+ u8 ca_cert_hash[SHA256_DIGEST_LENGTH];
7580+
7581+ int *ciphersuites; /* list of ciphersuite ids for mbedtls_ssl_config */
7582+#if MBEDTLS_VERSION_NUMBER < 0x03010000 /* mbedtls 3.1.0 */
7583+ mbedtls_ecp_group_id *curves;
7584+#else
7585+ uint16_t *curves; /* list of curve ids for mbedtls_ssl_config */
7586+#endif
7587+};
7588+
7589+
7590+struct tls_global {
7591+ struct tls_conf *tls_conf;
7592+ char *ocsp_stapling_response;
7593+ mbedtls_ctr_drbg_context *ctr_drbg; /*(see crypto_mbedtls.c)*/
7594+ #ifdef MBEDTLS_SSL_SESSION_TICKETS
7595+ mbedtls_ssl_ticket_context ticket_ctx;
7596+ #endif
7597+ char *ca_cert_file;
7598+ struct os_reltime crl_reload_previous;
7599+ unsigned int crl_reload_interval;
7600+ uint32_t refcnt;
7601+ struct tls_config init_conf;
7602+};
7603+
7604+static struct tls_global tls_ctx_global;
7605+
7606+
7607+struct tls_connection {
7608+ struct tls_conf *tls_conf;
7609+ struct wpabuf *push_buf;
7610+ struct wpabuf *pull_buf;
7611+ size_t pull_buf_offset;
7612+
7613+ unsigned int established:1;
7614+ unsigned int resumed:1;
7615+ unsigned int verify_peer:1;
7616+ unsigned int is_server:1;
7617+
7618+ mbedtls_ssl_context ssl;
7619+
7620+ mbedtls_tls_prf_types tls_prf_type;
7621+ size_t expkey_keyblock_size;
7622+ size_t expkey_secret_len;
7623+ #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */
7624+ unsigned char expkey_secret[MBEDTLS_EXPKEY_FIXED_SECRET_LEN];
7625+ #else
7626+ unsigned char expkey_secret[MBEDTLS_MD_MAX_SIZE];
7627+ #endif
7628+ unsigned char expkey_randbytes[MBEDTLS_EXPKEY_RAND_LEN*2];
7629+
7630+ int read_alerts, write_alerts, failed;
7631+
7632+ #ifdef TLS_MBEDTLS_SESSION_TICKETS
7633+ tls_session_ticket_cb session_ticket_cb;
7634+ void *session_ticket_cb_ctx;
7635+ unsigned char *clienthello_session_ticket;
7636+ size_t clienthello_session_ticket_len;
7637+ #endif
7638+ char *peer_subject; /* peer subject info for authenticated peer */
7639+ struct wpabuf *success_data;
7640+};
7641+
7642+
7643+#ifndef __has_attribute
7644+#define __has_attribute(x) 0
7645+#endif
7646+
7647+#ifndef __GNUC_PREREQ
7648+#define __GNUC_PREREQ(maj,min) 0
7649+#endif
7650+
7651+#ifndef __attribute_cold__
7652+#if __has_attribute(cold) \
7653+ || __GNUC_PREREQ(4,3)
7654+#define __attribute_cold__ __attribute__((__cold__))
7655+#else
7656+#define __attribute_cold__
7657+#endif
7658+#endif
7659+
7660+#ifndef __attribute_noinline__
7661+#if __has_attribute(noinline) \
7662+ || __GNUC_PREREQ(3,1)
7663+#define __attribute_noinline__ __attribute__((__noinline__))
7664+#else
7665+#define __attribute_noinline__
7666+#endif
7667+#endif
7668+
7669+
7670+__attribute_cold__
7671+__attribute_noinline__
7672+static void emsg(int level, const char * const msg)
7673+{
7674+ wpa_printf(level, "MTLS: %s", msg);
7675+}
7676+
7677+
7678+__attribute_cold__
7679+__attribute_noinline__
7680+static void emsgrc(int level, const char * const msg, int rc)
7681+{
7682+ #ifdef MBEDTLS_ERROR_C
7683+ /* error logging convenience function that decodes mbedtls result codes */
7684+ char buf[256];
7685+ mbedtls_strerror(rc, buf, sizeof(buf));
7686+ wpa_printf(level, "MTLS: %s: %s (-0x%04x)", msg, buf, -rc);
7687+ #else
7688+ wpa_printf(level, "MTLS: %s: (-0x%04x)", msg, -rc);
7689+ #endif
7690+}
7691+
7692+
7693+#define elog(rc, msg) emsgrc(MSG_ERROR, (msg), (rc))
7694+#define ilog(rc, msg) emsgrc(MSG_INFO, (msg), (rc))
7695+
7696+
7697+struct tls_conf * tls_conf_init(void *tls_ctx)
7698+{
7699+ struct tls_conf *tls_conf = os_zalloc(sizeof(*tls_conf));
7700+ if (tls_conf == NULL)
7701+ return NULL;
7702+ tls_conf->refcnt = 1;
7703+
7704+ mbedtls_ssl_config_init(&tls_conf->conf);
7705+ mbedtls_ssl_conf_rng(&tls_conf->conf,
7706+ mbedtls_ctr_drbg_random, tls_ctx_global.ctr_drbg);
7707+ mbedtls_x509_crt_init(&tls_conf->ca_cert);
7708+ mbedtls_x509_crt_init(&tls_conf->client_cert);
7709+ mbedtls_pk_init(&tls_conf->private_key);
7710+
7711+ return tls_conf;
7712+}
7713+
7714+
7715+void tls_conf_deinit(struct tls_conf *tls_conf)
7716+{
7717+ if (tls_conf == NULL || --tls_conf->refcnt != 0)
7718+ return;
7719+
7720+ mbedtls_x509_crt_free(&tls_conf->ca_cert);
7721+ mbedtls_x509_crt_free(&tls_conf->client_cert);
7722+ if (tls_conf->crl) {
7723+ mbedtls_x509_crl_free(tls_conf->crl);
7724+ os_free(tls_conf->crl);
7725+ }
7726+ mbedtls_pk_free(&tls_conf->private_key);
7727+ mbedtls_ssl_config_free(&tls_conf->conf);
7728+ os_free(tls_conf->curves);
7729+ os_free(tls_conf->ciphersuites);
7730+ os_free(tls_conf->subject_match);
7731+ os_free(tls_conf->altsubject_match);
7732+ os_free(tls_conf->suffix_match);
7733+ os_free(tls_conf->domain_match);
7734+ os_free(tls_conf->check_cert_subject);
7735+ os_free(tls_conf);
7736+}
7737+
7738+
7739+mbedtls_ctr_drbg_context * crypto_mbedtls_ctr_drbg(void); /*(not in header)*/
7740+
7741+__attribute_cold__
7742+void * tls_init(const struct tls_config *conf)
7743+{
7744+ /* RFE: review struct tls_config *conf (different from tls_conf) */
7745+
7746+ if (++tls_ctx_global.refcnt > 1)
7747+ return &tls_ctx_global;
7748+
7749+ tls_ctx_global.ctr_drbg = crypto_mbedtls_ctr_drbg();
7750+ #ifdef MBEDTLS_SSL_SESSION_TICKETS
7751+ mbedtls_ssl_ticket_init(&tls_ctx_global.ticket_ctx);
7752+ mbedtls_ssl_ticket_setup(&tls_ctx_global.ticket_ctx,
7753+ mbedtls_ctr_drbg_random,
7754+ tls_ctx_global.ctr_drbg,
7755+ MBEDTLS_CIPHER_AES_256_GCM,
7756+ 43200); /* ticket timeout: 12 hours */
7757+ #endif
7758+ /* copy struct for future use */
7759+ tls_ctx_global.init_conf = *conf;
7760+ if (conf->openssl_ciphers)
7761+ tls_ctx_global.init_conf.openssl_ciphers =
7762+ os_strdup(conf->openssl_ciphers);
7763+
7764+ tls_ctx_global.crl_reload_interval = conf->crl_reload_interval;
7765+ os_get_reltime(&tls_ctx_global.crl_reload_previous);
7766+
7767+ return &tls_ctx_global;
7768+}
7769+
7770+
7771+__attribute_cold__
7772+void tls_deinit(void *tls_ctx)
7773+{
7774+ if (tls_ctx == NULL || --tls_ctx_global.refcnt != 0)
7775+ return;
7776+
7777+ tls_conf_deinit(tls_ctx_global.tls_conf);
7778+ os_free(tls_ctx_global.ca_cert_file);
7779+ os_free(tls_ctx_global.ocsp_stapling_response);
7780+ char *openssl_ciphers; /*(allocated in tls_init())*/
7781+ *(const char **)&openssl_ciphers =
7782+ tls_ctx_global.init_conf.openssl_ciphers;
7783+ os_free(openssl_ciphers);
7784+ #ifdef MBEDTLS_SSL_SESSION_TICKETS
7785+ mbedtls_ssl_ticket_free(&tls_ctx_global.ticket_ctx);
7786+ #endif
7787+ os_memset(&tls_ctx_global, 0, sizeof(tls_ctx_global));
7788+}
7789+
7790+
7791+int tls_get_errors(void *tls_ctx)
7792+{
7793+ return 0;
7794+}
7795+
7796+
7797+static void tls_connection_deinit_expkey(struct tls_connection *conn)
7798+{
7799+ conn->tls_prf_type = 0; /* MBEDTLS_SSL_TLS_PRF_NONE; */
7800+ conn->expkey_keyblock_size = 0;
7801+ conn->expkey_secret_len = 0;
7802+ forced_memzero(conn->expkey_secret, sizeof(conn->expkey_secret));
7803+ forced_memzero(conn->expkey_randbytes, sizeof(conn->expkey_randbytes));
7804+}
7805+
7806+
7807+#ifdef TLS_MBEDTLS_SESSION_TICKETS
7808+void tls_connection_deinit_clienthello_session_ticket(struct tls_connection *conn)
7809+{
7810+ if (conn->clienthello_session_ticket) {
7811+ mbedtls_platform_zeroize(conn->clienthello_session_ticket,
7812+ conn->clienthello_session_ticket_len);
7813+ mbedtls_free(conn->clienthello_session_ticket);
7814+ conn->clienthello_session_ticket = NULL;
7815+ conn->clienthello_session_ticket_len = 0;
7816+ }
7817+}
7818+#endif
7819+
7820+
7821+void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn)
7822+{
7823+ if (conn == NULL)
7824+ return;
7825+
7826+ #if 0 /*(good intention, but never sent since we destroy self below)*/
7827+ if (conn->established)
7828+ mbedtls_ssl_close_notify(&conn->ssl);
7829+ #endif
7830+
7831+ if (conn->tls_prf_type)
7832+ tls_connection_deinit_expkey(conn);
7833+
7834+ #ifdef TLS_MBEDTLS_SESSION_TICKETS
7835+ if (conn->clienthello_session_ticket)
7836+ tls_connection_deinit_clienthello_session_ticket(conn);
7837+ #endif
7838+
7839+ os_free(conn->peer_subject);
7840+ wpabuf_free(conn->success_data);
7841+ wpabuf_free(conn->push_buf);
7842+ wpabuf_free(conn->pull_buf);
7843+ mbedtls_ssl_free(&conn->ssl);
7844+ tls_conf_deinit(conn->tls_conf);
7845+ os_free(conn);
7846+}
7847+
7848+
7849+static void tls_mbedtls_refresh_crl(void);
7850+static int tls_mbedtls_ssl_setup(struct tls_connection *conn);
7851+
7852+struct tls_connection * tls_connection_init(void *tls_ctx)
7853+{
7854+ struct tls_connection *conn = os_zalloc(sizeof(*conn));
7855+ if (conn == NULL)
7856+ return NULL;
7857+
7858+ mbedtls_ssl_init(&conn->ssl);
7859+
7860+ conn->tls_conf = tls_ctx_global.tls_conf; /*(inherit global conf, if set)*/
7861+ if (conn->tls_conf) {
7862+ ++conn->tls_conf->refcnt;
7863+ /* check for CRL refresh if inheriting from global config */
7864+ tls_mbedtls_refresh_crl();
7865+
7866+ conn->verify_peer = conn->tls_conf->verify_peer;
7867+ if (tls_mbedtls_ssl_setup(conn) != 0) {
7868+ tls_connection_deinit(&tls_ctx_global, conn);
7869+ return NULL;
7870+ }
7871+ }
7872+
7873+ return conn;
7874+}
7875+
7876+
7877+int tls_connection_established(void *tls_ctx, struct tls_connection *conn)
7878+{
7879+ return conn ? conn->established : 0;
7880+}
7881+
7882+
7883+__attribute_noinline__
7884+char * tls_mbedtls_peer_serial_num(const mbedtls_x509_crt *crt, char *serial_num, size_t len)
7885+{
7886+ /* mbedtls_x509_serial_gets() inefficiently formats to hex separated by
7887+ * colons, so generate the hex serial number here. The func
7888+ * wpa_snprintf_hex_uppercase() is similarly inefficient. */
7889+ size_t i = 0; /* skip leading 0's per Distinguished Encoding Rules (DER) */
7890+ while (i < crt->serial.len && crt->serial.p[i] == 0) ++i;
7891+ if (i == crt->serial.len) --i;
7892+
7893+ const unsigned char *s = crt->serial.p + i;
7894+ const size_t e = (crt->serial.len - i) * 2;
7895+ if (e >= len)
7896+ return NULL;
7897+ #if 0
7898+ wpa_snprintf_hex_uppercase(serial_num, len, s, crt->serial.len-i);
7899+ #else
7900+ for (i = 0; i < e; i+=2, ++s) {
7901+ serial_num[i+0] = "0123456789ABCDEF"[(*s >> 4)];
7902+ serial_num[i+1] = "0123456789ABCDEF"[(*s & 0xF)];
7903+ }
7904+ serial_num[e] = '\0';
7905+ #endif
7906+ return serial_num;
7907+}
7908+
7909+
7910+char * tls_connection_peer_serial_num(void *tls_ctx,
7911+ struct tls_connection *conn)
7912+{
7913+ const mbedtls_x509_crt *crt = mbedtls_ssl_get_peer_cert(&conn->ssl);
7914+ if (crt == NULL)
7915+ return NULL;
7916+ size_t len = crt->serial.len * 2 + 1;
7917+ char *serial_num = os_malloc(len);
7918+ if (!serial_num)
7919+ return NULL;
7920+ return tls_mbedtls_peer_serial_num(crt, serial_num, len);
7921+}
7922+
7923+
7924+static void tls_pull_buf_reset(struct tls_connection *conn);
7925+
7926+int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn)
7927+{
7928+ /* Note: this function called from eap_peer_tls_reauth_init()
7929+ * for session resumption, not for connection shutdown */
7930+
7931+ if (conn == NULL)
7932+ return -1;
7933+
7934+ tls_pull_buf_reset(conn);
7935+ wpabuf_free(conn->push_buf);
7936+ conn->push_buf = NULL;
7937+ conn->established = 0;
7938+ conn->resumed = 0;
7939+ if (conn->tls_prf_type)
7940+ tls_connection_deinit_expkey(conn);
7941+
7942+ /* RFE: prepare for session resumption? (see doc in crypto/tls.h) */
7943+
7944+ return mbedtls_ssl_session_reset(&conn->ssl);
7945+}
7946+
7947+
7948+static int tls_wpabuf_resize_put_data(struct wpabuf **buf,
7949+ const unsigned char *data, size_t dlen)
7950+{
7951+ if (wpabuf_resize(buf, dlen) < 0)
7952+ return 0;
7953+ wpabuf_put_data(*buf, data, dlen);
7954+ return 1;
7955+}
7956+
7957+
7958+static int tls_pull_buf_append(struct tls_connection *conn,
7959+ const struct wpabuf *in_data)
7960+{
7961+ /*(interface does not lend itself to move semantics)*/
7962+ return tls_wpabuf_resize_put_data(&conn->pull_buf,
7963+ wpabuf_head(in_data),
7964+ wpabuf_len(in_data));
7965+}
7966+
7967+
7968+static void tls_pull_buf_reset(struct tls_connection *conn)
7969+{
7970+ /*(future: might consider reusing conn->pull_buf)*/
7971+ wpabuf_free(conn->pull_buf);
7972+ conn->pull_buf = NULL;
7973+ conn->pull_buf_offset = 0;
7974+}
7975+
7976+
7977+__attribute_cold__
7978+static void tls_pull_buf_discard(struct tls_connection *conn, const char *func)
7979+{
7980+ size_t discard = wpabuf_len(conn->pull_buf) - conn->pull_buf_offset;
7981+ if (discard)
7982+ wpa_printf(MSG_DEBUG,
7983+ "%s - %zu bytes remaining in pull_buf; discarding",
7984+ func, discard);
7985+ tls_pull_buf_reset(conn);
7986+}
7987+
7988+
7989+static int tls_pull_func(void *ptr, unsigned char *buf, size_t len)
7990+{
7991+ struct tls_connection *conn = (struct tls_connection *) ptr;
7992+ if (conn->pull_buf == NULL)
7993+ return MBEDTLS_ERR_SSL_WANT_READ;
7994+ const size_t dlen = wpabuf_len(conn->pull_buf) - conn->pull_buf_offset;
7995+ if (dlen == 0)
7996+ return MBEDTLS_ERR_SSL_WANT_READ;
7997+
7998+ if (len > dlen)
7999+ len = dlen;
8000+ os_memcpy(buf, wpabuf_head(conn->pull_buf)+conn->pull_buf_offset, len);
8001+
8002+ if (len == dlen) {
8003+ tls_pull_buf_reset(conn);
8004+ /*wpa_printf(MSG_DEBUG, "%s - emptied pull_buf", __func__);*/
8005+ }
8006+ else {
8007+ conn->pull_buf_offset += len;
8008+ /*wpa_printf(MSG_DEBUG, "%s - %zu bytes remaining in pull_buf",
8009+ __func__, dlen - len);*/
8010+ }
8011+ return (int)len;
8012+}
8013+
8014+
8015+static int tls_push_func(void *ptr, const unsigned char *buf, size_t len)
8016+{
8017+ struct tls_connection *conn = (struct tls_connection *) ptr;
8018+ return tls_wpabuf_resize_put_data(&conn->push_buf, buf, len)
8019+ ? (int)len
8020+ : MBEDTLS_ERR_SSL_ALLOC_FAILED;
8021+}
8022+
8023+
8024+static int
8025+tls_mbedtls_verify_cb (void *arg, mbedtls_x509_crt *crt, int depth, uint32_t *flags);
8026+
8027+
8028+static int tls_mbedtls_ssl_setup(struct tls_connection *conn)
8029+{
8030+ #if 0
8031+ /* mbedtls_ssl_setup() must be called only once */
8032+ /* If this func might be called multiple times (e.g. via set_params),
8033+ * then we should set a flag in conn that ssl was initialized */
8034+ if (conn->ssl_is_init) {
8035+ mbedtls_ssl_free(&conn->ssl);
8036+ mbedtls_ssl_init(&conn->ssl);
8037+ }
8038+ #endif
8039+
8040+ int ret = mbedtls_ssl_setup(&conn->ssl, &conn->tls_conf->conf);
8041+ if (ret != 0) {
8042+ elog(ret, "mbedtls_ssl_setup");
8043+ return -1;
8044+ }
8045+
8046+ mbedtls_ssl_set_bio(&conn->ssl, conn, tls_push_func, tls_pull_func, NULL);
8047+ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
8048+ mbedtls_ssl_set_export_keys_cb(
8049+ &conn->ssl, tls_connection_export_keys_cb, conn);
8050+ #elif MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */
8051+ mbedtls_ssl_conf_export_keys_ext_cb(
8052+ &conn->tls_conf->conf, tls_connection_export_keys_cb, conn);
8053+ #endif
8054+ if (conn->verify_peer)
8055+ mbedtls_ssl_set_verify(&conn->ssl, tls_mbedtls_verify_cb, conn);
8056+
8057+ return 0;
8058+}
8059+
8060+
8061+static int tls_mbedtls_data_is_pem(const u8 *data)
8062+{
8063+ return (NULL != os_strstr((char *)data, "-----"));
8064+}
8065+
8066+
8067+static void tls_mbedtls_set_allowed_tls_vers(struct tls_conf *tls_conf,
8068+ mbedtls_ssl_config *conf)
8069+{
8070+ #if !defined(MBEDTLS_SSL_PROTO_TLS1_3)
8071+ tls_conf->flags |= TLS_CONN_DISABLE_TLSv1_3;
8072+ #endif
8073+
8074+ /* unconditionally require TLSv1.2+ for TLS_CONN_SUITEB */
8075+ if (tls_conf->flags & TLS_CONN_SUITEB) {
8076+ tls_conf->flags |= TLS_CONN_DISABLE_TLSv1_0;
8077+ tls_conf->flags |= TLS_CONN_DISABLE_TLSv1_1;
8078+ }
8079+
8080+ const unsigned int flags = tls_conf->flags;
8081+
8082+ /* attempt to map flags to min and max TLS protocol version */
8083+
8084+ int min = (flags & TLS_CONN_DISABLE_TLSv1_0)
8085+ ? (flags & TLS_CONN_DISABLE_TLSv1_1)
8086+ ? (flags & TLS_CONN_DISABLE_TLSv1_2)
8087+ ? (flags & TLS_CONN_DISABLE_TLSv1_3)
8088+ ? 4
8089+ : 3
8090+ : 2
8091+ : 1
8092+ : 0;
8093+
8094+ int max = (flags & TLS_CONN_DISABLE_TLSv1_3)
8095+ ? (flags & TLS_CONN_DISABLE_TLSv1_2)
8096+ ? (flags & TLS_CONN_DISABLE_TLSv1_1)
8097+ ? (flags & TLS_CONN_DISABLE_TLSv1_0)
8098+ ? -1
8099+ : 0
8100+ : 1
8101+ : 2
8102+ : 3;
8103+
8104+ if ((flags & TLS_CONN_ENABLE_TLSv1_2) && min > 2) min = 2;
8105+ if ((flags & TLS_CONN_ENABLE_TLSv1_1) && min > 1) min = 1;
8106+ if ((flags & TLS_CONN_ENABLE_TLSv1_0) && min > 0) min = 0;
8107+ if (max < min) {
8108+ emsg(MSG_ERROR, "invalid tls_disable_tlsv* params; ignoring");
8109+ return;
8110+ }
8111+ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
8112+ /* mbed TLS 3.0.0 removes support for protocols < TLSv1.2 */
8113+ if (min < 2 || max < 2) {
8114+ emsg(MSG_ERROR, "invalid tls_disable_tlsv* params; ignoring");
8115+ if (min < 2) min = 2;
8116+ if (max < 2) max = 2;
8117+ }
8118+ #endif
8119+
8120+ #if MBEDTLS_VERSION_NUMBER >= 0x03020000 /* mbedtls 3.2.0 */
8121+ /* MBEDTLS_SSL_VERSION_TLS1_2 = 0x0303 *//*!< (D)TLS 1.2 */
8122+ /* MBEDTLS_SSL_VERSION_TLS1_3 = 0x0304 *//*!< (D)TLS 1.3 */
8123+ min = (min == 2) ? MBEDTLS_SSL_VERSION_TLS1_2 : MBEDTLS_SSL_VERSION_TLS1_3;
8124+ max = (max == 2) ? MBEDTLS_SSL_VERSION_TLS1_2 : MBEDTLS_SSL_VERSION_TLS1_3;
8125+ mbedtls_ssl_conf_min_tls_version(conf, min);
8126+ mbedtls_ssl_conf_max_tls_version(conf, max);
8127+ #else
8128+ #ifndef MBEDTLS_SSL_MINOR_VERSION_4
8129+ if (min == 3) min = 2;
8130+ if (max == 3) max = 2;
8131+ #endif
8132+ /* MBEDTLS_SSL_MINOR_VERSION_0 0 *//*!< SSL v3.0 */
8133+ /* MBEDTLS_SSL_MINOR_VERSION_1 1 *//*!< TLS v1.0 */
8134+ /* MBEDTLS_SSL_MINOR_VERSION_2 2 *//*!< TLS v1.1 */
8135+ /* MBEDTLS_SSL_MINOR_VERSION_3 3 *//*!< TLS v1.2 */
8136+ /* MBEDTLS_SSL_MINOR_VERSION_4 4 *//*!< TLS v1.3 */
8137+ mbedtls_ssl_conf_min_version(conf, MBEDTLS_SSL_MAJOR_VERSION_3, min+1);
8138+ mbedtls_ssl_conf_max_version(conf, MBEDTLS_SSL_MAJOR_VERSION_3, max+1);
8139+ #endif
8140+}
8141+
8142+
8143+__attribute_noinline__
8144+static int tls_mbedtls_readfile(const char *path, u8 **buf, size_t *n);
8145+
8146+
8147+static int
8148+tls_mbedtls_set_dhparams(struct tls_conf *tls_conf, const char *dh_file)
8149+{
8150+ size_t len;
8151+ u8 *data;
8152+ if (tls_mbedtls_readfile(dh_file, &data, &len))
8153+ return 0;
8154+
8155+ /* parse only if DH parameters if in PEM format */
8156+ if (tls_mbedtls_data_is_pem(data)
8157+ && NULL == os_strstr((char *)data, "-----BEGIN DH PARAMETERS-----")) {
8158+ if (os_strstr((char *)data, "-----BEGIN DSA PARAMETERS-----"))
8159+ wpa_printf(MSG_WARNING, "DSA parameters not handled (%s)", dh_file);
8160+ else
8161+ wpa_printf(MSG_WARNING, "unexpected DH param content (%s)",dh_file);
8162+ forced_memzero(data, len);
8163+ os_free(data);
8164+ return 0;
8165+ }
8166+
8167+ /* mbedtls_dhm_parse_dhm() expects "-----BEGIN DH PARAMETERS-----" if PEM */
8168+ mbedtls_dhm_context dhm;
8169+ mbedtls_dhm_init(&dhm);
8170+ int rc = mbedtls_dhm_parse_dhm(&dhm, data, len);
8171+ if (0 == rc)
8172+ rc = mbedtls_ssl_conf_dh_param_ctx(&tls_conf->conf, &dhm);
8173+ if (0 != rc)
8174+ elog(rc, dh_file);
8175+ mbedtls_dhm_free(&dhm);
8176+
8177+ forced_memzero(data, len);
8178+ os_free(data);
8179+ return (0 == rc);
8180+}
8181+
8182+
8183+/* reference: lighttpd src/mod_mbedtls.c:mod_mbedtls_ssl_append_curve()
8184+ * (same author: gstrauss@gluelogic.com; same license: BSD-3-Clause) */
8185+#if MBEDTLS_VERSION_NUMBER < 0x03010000 /* mbedtls 3.1.0 */
8186+static int
8187+tls_mbedtls_append_curve (mbedtls_ecp_group_id *ids, int nids, int idsz, const mbedtls_ecp_group_id id)
8188+{
8189+ if (1 >= idsz - (nids + 1)) {
8190+ emsg(MSG_ERROR, "error: too many curves during list expand");
8191+ return -1;
8192+ }
8193+ ids[++nids] = id;
8194+ return nids;
8195+}
8196+
8197+
8198+static int
8199+tls_mbedtls_set_curves(struct tls_conf *tls_conf, const char *curvelist)
8200+{
8201+ mbedtls_ecp_group_id ids[512];
8202+ int nids = -1;
8203+ const int idsz = (int)(sizeof(ids)/sizeof(*ids)-1);
8204+ const mbedtls_ecp_curve_info * const curve_info = mbedtls_ecp_curve_list();
8205+
8206+ for (const char *e = curvelist-1; e; ) {
8207+ const char * const n = e+1;
8208+ e = os_strchr(n, ':');
8209+ size_t len = e ? (size_t)(e - n) : os_strlen(n);
8210+ mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE;
8211+ switch (len) {
8212+ case 5:
8213+ if (0 == os_memcmp("P-521", n, 5))
8214+ grp_id = MBEDTLS_ECP_DP_SECP521R1;
8215+ else if (0 == os_memcmp("P-384", n, 5))
8216+ grp_id = MBEDTLS_ECP_DP_SECP384R1;
8217+ else if (0 == os_memcmp("P-256", n, 5))
8218+ grp_id = MBEDTLS_ECP_DP_SECP256R1;
8219+ break;
8220+ case 6:
8221+ if (0 == os_memcmp("BP-521", n, 6))
8222+ grp_id = MBEDTLS_ECP_DP_BP512R1;
8223+ else if (0 == os_memcmp("BP-384", n, 6))
8224+ grp_id = MBEDTLS_ECP_DP_BP384R1;
8225+ else if (0 == os_memcmp("BP-256", n, 6))
8226+ grp_id = MBEDTLS_ECP_DP_BP256R1;
8227+ break;
8228+ default:
8229+ break;
8230+ }
8231+ if (grp_id != MBEDTLS_ECP_DP_NONE) {
8232+ nids = tls_mbedtls_append_curve(ids, nids, idsz, grp_id);
8233+ if (-1 == nids) return 0;
8234+ continue;
8235+ }
8236+ /* similar to mbedtls_ecp_curve_info_from_name() */
8237+ const mbedtls_ecp_curve_info *info;
8238+ for (info = curve_info; info->grp_id != MBEDTLS_ECP_DP_NONE; ++info) {
8239+ if (0 == os_strncmp(info->name, n, len) && info->name[len] == '\0')
8240+ break;
8241+ }
8242+ if (info->grp_id == MBEDTLS_ECP_DP_NONE) {
8243+ wpa_printf(MSG_ERROR, "MTLS: unrecognized curve: %.*s",(int)len,n);
8244+ return 0;
8245+ }
8246+
8247+ nids = tls_mbedtls_append_curve(ids, nids, idsz, info->grp_id);
8248+ if (-1 == nids) return 0;
8249+ }
8250+
8251+ /* mod_openssl configures "prime256v1" if curve list not specified,
8252+ * but mbedtls provides a list of supported curves if not explicitly set */
8253+ if (-1 == nids) return 1; /* empty list; no-op */
8254+
8255+ ids[++nids] = MBEDTLS_ECP_DP_NONE; /* terminate list */
8256+ ++nids;
8257+
8258+ /* curves list must be persistent for lifetime of mbedtls_ssl_config */
8259+ tls_conf->curves = os_malloc(nids * sizeof(mbedtls_ecp_group_id));
8260+ if (tls_conf->curves == NULL)
8261+ return 0;
8262+ os_memcpy(tls_conf->curves, ids, nids * sizeof(mbedtls_ecp_group_id));
8263+
8264+ mbedtls_ssl_conf_curves(&tls_conf->conf, tls_conf->curves);
8265+ return 1;
8266+}
8267+#else
8268+static int
8269+tls_mbedtls_append_curve (uint16_t *ids, int nids, int idsz, const uint16_t id)
8270+{
8271+ if (1 >= idsz - (nids + 1)) {
8272+ emsg(MSG_ERROR, "error: too many curves during list expand");
8273+ return -1;
8274+ }
8275+ ids[++nids] = id;
8276+ return nids;
8277+}
8278+
8279+
8280+static int
8281+tls_mbedtls_set_curves(struct tls_conf *tls_conf, const char *curvelist)
8282+{
8283+ /* TLS Supported Groups (renamed from "EC Named Curve Registry")
8284+ * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8
8285+ */
8286+ uint16_t ids[512];
8287+ int nids = -1;
8288+ const int idsz = (int)(sizeof(ids)/sizeof(*ids)-1);
8289+ const mbedtls_ecp_curve_info * const curve_info = mbedtls_ecp_curve_list();
8290+
8291+ for (const char *e = curvelist-1; e; ) {
8292+ const char * const n = e+1;
8293+ e = os_strchr(n, ':');
8294+ size_t len = e ? (size_t)(e - n) : os_strlen(n);
8295+ uint16_t tls_id = 0;
8296+ switch (len) {
8297+ case 5:
8298+ if (0 == os_memcmp("P-521", n, 5))
8299+ tls_id = 25; /* mbedtls_ecp_group_id MBEDTLS_ECP_DP_SECP521R1 */
8300+ else if (0 == os_memcmp("P-384", n, 5))
8301+ tls_id = 24; /* mbedtls_ecp_group_id MBEDTLS_ECP_DP_SECP384R1 */
8302+ else if (0 == os_memcmp("P-256", n, 5))
8303+ tls_id = 23; /* mbedtls_ecp_group_id MBEDTLS_ECP_DP_SECP256R1 */
8304+ break;
8305+ case 6:
8306+ if (0 == os_memcmp("BP-521", n, 6))
8307+ tls_id = 28; /* mbedtls_ecp_group_id MBEDTLS_ECP_DP_BP512R1 */
8308+ else if (0 == os_memcmp("BP-384", n, 6))
8309+ tls_id = 27; /* mbedtls_ecp_group_id MBEDTLS_ECP_DP_BP384R1 */
8310+ else if (0 == os_memcmp("BP-256", n, 6))
8311+ tls_id = 26; /* mbedtls_ecp_group_id MBEDTLS_ECP_DP_BP256R1 */
8312+ break;
8313+ default:
8314+ break;
8315+ }
8316+ if (tls_id != 0) {
8317+ nids = tls_mbedtls_append_curve(ids, nids, idsz, tls_id);
8318+ if (-1 == nids) return 0;
8319+ continue;
8320+ }
8321+ /* similar to mbedtls_ecp_curve_info_from_name() */
8322+ const mbedtls_ecp_curve_info *info;
8323+ for (info = curve_info; info->tls_id != 0; ++info) {
8324+ if (0 == os_strncmp(info->name, n, len) && info->name[len] == '\0')
8325+ break;
8326+ }
8327+ if (info->tls_id == 0) {
8328+ wpa_printf(MSG_ERROR, "MTLS: unrecognized curve: %.*s",(int)len,n);
8329+ return 0;
8330+ }
8331+
8332+ nids = tls_mbedtls_append_curve(ids, nids, idsz, info->tls_id);
8333+ if (-1 == nids) return 0;
8334+ }
8335+
8336+ /* mod_openssl configures "prime256v1" if curve list not specified,
8337+ * but mbedtls provides a list of supported curves if not explicitly set */
8338+ if (-1 == nids) return 1; /* empty list; no-op */
8339+
8340+ ids[++nids] = 0; /* terminate list */
8341+ ++nids;
8342+
8343+ /* curves list must be persistent for lifetime of mbedtls_ssl_config */
8344+ tls_conf->curves = os_malloc(nids * sizeof(uint16_t));
8345+ if (tls_conf->curves == NULL)
8346+ return 0;
8347+ os_memcpy(tls_conf->curves, ids, nids * sizeof(uint16_t));
8348+
8349+ mbedtls_ssl_conf_groups(&tls_conf->conf, tls_conf->curves);
8350+ return 1;
8351+}
8352+#endif /* MBEDTLS_VERSION_NUMBER >= 0x03010000 */ /* mbedtls 3.1.0 */
8353+
8354+
8355+/* data copied from lighttpd src/mod_mbedtls.c (BSD-3-Clause) */
8356+static const int suite_AES_256_ephemeral[] = {
8357+ /* All AES-256 ephemeral suites */
8358+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
8359+ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
8360+ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
8361+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM,
8362+ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM,
8363+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
8364+ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
8365+ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
8366+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
8367+ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
8368+ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
8369+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8,
8370+ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8
8371+};
8372+
8373+/* data copied from lighttpd src/mod_mbedtls.c (BSD-3-Clause) */
8374+static const int suite_AES_128_ephemeral[] = {
8375+ /* All AES-128 ephemeral suites */
8376+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
8377+ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
8378+ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
8379+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM,
8380+ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM,
8381+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
8382+ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
8383+ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
8384+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
8385+ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
8386+ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
8387+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,
8388+ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8
8389+};
8390+
8391+/* data copied from lighttpd src/mod_mbedtls.c (BSD-3-Clause) */
8392+/* HIGH cipher list (mapped from openssl list to mbedtls) */
8393+static const int suite_HIGH[] = {
8394+ MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
8395+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
8396+ MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
8397+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
8398+ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
8399+ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
8400+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM,
8401+ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM,
8402+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
8403+ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
8404+ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
8405+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
8406+ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
8407+ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
8408+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8,
8409+ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8,
8410+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
8411+ MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,
8412+ MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
8413+ MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
8414+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384,
8415+ MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384,
8416+ MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384,
8417+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
8418+ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
8419+ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
8420+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM,
8421+ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM,
8422+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
8423+ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
8424+ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
8425+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
8426+ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
8427+ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
8428+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,
8429+ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8,
8430+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
8431+ MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
8432+ MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
8433+ MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
8434+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256,
8435+ MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256,
8436+ MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256,
8437+ MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
8438+ MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
8439+ MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,
8440+ MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM,
8441+ MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
8442+ MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,
8443+ MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA,
8444+ MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA,
8445+ MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
8446+ MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
8447+ MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8,
8448+ MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384,
8449+ MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256,
8450+ MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM,
8451+ MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
8452+ MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
8453+ MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
8454+ MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA,
8455+ MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
8456+ MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
8457+ MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8,
8458+ MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256,
8459+ MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384,
8460+ MBEDTLS_TLS_RSA_WITH_AES_256_CCM,
8461+ MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256,
8462+ MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA,
8463+ MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8,
8464+ MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,
8465+ MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,
8466+ MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384,
8467+ MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256,
8468+ MBEDTLS_TLS_RSA_WITH_AES_128_CCM,
8469+ MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256,
8470+ MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA,
8471+ MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8,
8472+ MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,
8473+ MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,
8474+ MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256,
8475+ MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256,
8476+ MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,
8477+ MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,
8478+ MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA,
8479+ MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384,
8480+ MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384,
8481+ MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256,
8482+ MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256,
8483+ MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA,
8484+ MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256,
8485+ MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256,
8486+ MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256,
8487+ MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384,
8488+ MBEDTLS_TLS_PSK_WITH_AES_256_CCM,
8489+ MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384,
8490+ MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA,
8491+ MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384,
8492+ MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8,
8493+ MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384,
8494+ MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256,
8495+ MBEDTLS_TLS_PSK_WITH_AES_128_CCM,
8496+ MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256,
8497+ MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA,
8498+ MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256,
8499+ MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8,
8500+ MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256
8501+};
8502+
8503+
8504+__attribute_noinline__
8505+static int
8506+tls_mbedtls_append_ciphersuite (int *ids, int nids, int idsz, const int *x, int xsz)
8507+{
8508+ if (xsz >= idsz - (nids + 1)) {
8509+ emsg(MSG_ERROR, "error: too many ciphers during list expand");
8510+ return -1;
8511+ }
8512+
8513+ for (int i = 0; i < xsz; ++i)
8514+ ids[++nids] = x[i];
8515+
8516+ return nids;
8517+}
8518+
8519+
8520+static int
8521+tls_mbedtls_translate_ciphername(int id, char *buf, size_t buflen)
8522+{
8523+ const mbedtls_ssl_ciphersuite_t *info =
8524+ mbedtls_ssl_ciphersuite_from_id(id);
8525+ if (info == NULL)
8526+ return 0;
8527+ const char *name = mbedtls_ssl_ciphersuite_get_name(info);
8528+ const size_t len = os_strlen(name);
8529+ if (len == 7 && 0 == os_memcmp(name, "unknown", 7))
8530+ return 0;
8531+ if (len >= buflen)
8532+ return 0;
8533+ os_strlcpy(buf, name, buflen);
8534+
8535+ /* attempt to translate mbedtls string to openssl string
8536+ * (some heuristics; incomplete) */
8537+ size_t i = 0, j = 0;
8538+ if (buf[0] == 'T') {
8539+ if (os_strncmp(buf, "TLS1-3-", 7) == 0) {
8540+ buf[3] = '-';
8541+ j = 4; /* remove "1-3" from "TLS1-3-" prefix */
8542+ i = 7;
8543+ }
8544+ else if (os_strncmp(buf, "TLS-", 4) == 0)
8545+ i = 4; /* remove "TLS-" prefix */
8546+ }
8547+ for (; buf[i]; ++i) {
8548+ if (buf[i] == '-') {
8549+ if (i >= 3) {
8550+ if (0 == os_memcmp(buf+i-3, "AES", 3))
8551+ continue; /* "AES-" -> "AES" */
8552+ }
8553+ if (i >= 4) {
8554+ if (0 == os_memcmp(buf+i-4, "WITH", 4)) {
8555+ j -= 4; /* remove "WITH-" */
8556+ continue;
8557+ }
8558+ }
8559+ }
8560+ buf[j++] = buf[i];
8561+ }
8562+ buf[j] = '\0';
8563+
8564+ return j;
8565+}
8566+
8567+
8568+__attribute_noinline__
8569+static int
8570+tls_mbedtls_set_ciphersuites(struct tls_conf *tls_conf, int *ids, int nids)
8571+{
8572+ /* ciphersuites list must be persistent for lifetime of mbedtls_ssl_config*/
8573+ os_free(tls_conf->ciphersuites);
8574+ tls_conf->ciphersuites = os_malloc(nids * sizeof(int));
8575+ if (tls_conf->ciphersuites == NULL)
8576+ return 0;
8577+ os_memcpy(tls_conf->ciphersuites, ids, nids * sizeof(int));
8578+ mbedtls_ssl_conf_ciphersuites(&tls_conf->conf, tls_conf->ciphersuites);
8579+ return 1;
8580+}
8581+
8582+
8583+static int
8584+tls_mbedtls_set_ciphers(struct tls_conf *tls_conf, const char *ciphers)
8585+{
8586+ char buf[64];
8587+ int ids[512];
8588+ int nids = -1;
8589+ const int idsz = (int)(sizeof(ids)/sizeof(*ids)-1);
8590+ const char *next;
8591+ size_t blen, clen;
8592+ do {
8593+ next = os_strchr(ciphers, ':');
8594+ clen = next ? (size_t)(next - ciphers) : os_strlen(ciphers);
8595+ if (!clen)
8596+ continue;
8597+
8598+ /* special-case a select set of openssl group names for hwsim tests */
8599+ /* (review; remove excess code if tests are not run for non-OpenSSL?) */
8600+ if (clen == 9 && os_memcmp(ciphers, "SUITEB192", 9) == 0) {
8601+ static int ssl_preset_suiteb192_ciphersuites[] = {
8602+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
8603+ 0
8604+ };
8605+ return tls_mbedtls_set_ciphersuites(tls_conf,
8606+ ssl_preset_suiteb192_ciphersuites,
8607+ 2);
8608+ }
8609+ if (clen == 9 && os_memcmp(ciphers, "SUITEB128", 9) == 0) {
8610+ static int ssl_preset_suiteb128_ciphersuites[] = {
8611+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
8612+ 0
8613+ };
8614+ return tls_mbedtls_set_ciphersuites(tls_conf,
8615+ ssl_preset_suiteb128_ciphersuites,
8616+ 2);
8617+ }
8618+ if (clen == 7 && os_memcmp(ciphers, "DEFAULT", 7) == 0)
8619+ continue;
8620+ if (clen == 6 && os_memcmp(ciphers, "AES128", 6) == 0) {
8621+ nids = tls_mbedtls_append_ciphersuite(ids, nids, idsz,
8622+ suite_AES_128_ephemeral,
8623+ (int)ARRAY_SIZE(suite_AES_128_ephemeral));
8624+ if (nids == -1)
8625+ return 0;
8626+ continue;
8627+ }
8628+ if (clen == 6 && os_memcmp(ciphers, "AES256", 6) == 0) {
8629+ nids = tls_mbedtls_append_ciphersuite(ids, nids, idsz,
8630+ suite_AES_256_ephemeral,
8631+ (int)ARRAY_SIZE(suite_AES_256_ephemeral));
8632+ if (nids == -1)
8633+ return 0;
8634+ continue;
8635+ }
8636+ if (clen == 4 && os_memcmp(ciphers, "HIGH", 4) == 0) {
8637+ nids = tls_mbedtls_append_ciphersuite(ids, nids, idsz, suite_HIGH,
8638+ (int)ARRAY_SIZE(suite_HIGH));
8639+ if (nids == -1)
8640+ return 0;
8641+ continue;
8642+ }
8643+ /* ignore anonymous cipher group names (?not supported by mbedtls?) */
8644+ if (clen == 4 && os_memcmp(ciphers, "!ADH", 4) == 0)
8645+ continue;
8646+ if (clen == 6 && os_memcmp(ciphers, "-aECDH", 6) == 0)
8647+ continue;
8648+ if (clen == 7 && os_memcmp(ciphers, "-aECDSA", 7) == 0)
8649+ continue;
8650+
8651+ /* attempt to match mbedtls cipher names
8652+ * nb: does not support openssl group names or list manipulation syntax
8653+ * (alt: could copy almost 1200 lines (!!!) of lighttpd mod_mbedtls.c
8654+ * mod_mbedtls_ssl_conf_ciphersuites() to translate strings)
8655+ * note: not efficient to rewrite list for each ciphers entry,
8656+ * but this code is expected to run only at startup
8657+ */
8658+ const int *list = mbedtls_ssl_list_ciphersuites();
8659+ for (; *list; ++list) {
8660+ blen = tls_mbedtls_translate_ciphername(*list,buf,sizeof(buf));
8661+ if (!blen)
8662+ continue;
8663+
8664+ /* matching heuristics additional to translate_ciphername above */
8665+ if (blen == clen+4) {
8666+ char *cbc = os_strstr(buf, "CBC-");
8667+ if (cbc) {
8668+ os_memmove(cbc, cbc+4, blen-(cbc+4-buf)+1); /*(w/ '\0')*/
8669+ blen -= 4;
8670+ }
8671+ }
8672+ if (blen >= clen && os_memcmp(ciphers, buf, clen) == 0
8673+ && (blen == clen
8674+ || (blen == clen+7 && os_memcmp(buf+clen, "-SHA256", 7)))) {
8675+ if (1 >= idsz - (nids + 1)) {
8676+ emsg(MSG_ERROR,
8677+ "error: too many ciphers during list expand");
8678+ return 0;
8679+ }
8680+ ids[++nids] = *list;
8681+ break;
8682+ }
8683+ }
8684+ if (*list == 0) {
8685+ wpa_printf(MSG_ERROR,
8686+ "MTLS: unrecognized cipher: %.*s", (int)clen, ciphers);
8687+ return 0;
8688+ }
8689+ } while ((ciphers = next ? next+1 : NULL));
8690+
8691+ if (-1 == nids) return 1; /* empty list; no-op */
8692+
8693+ ids[++nids] = 0; /* terminate list */
8694+ ++nids;
8695+
8696+ return tls_mbedtls_set_ciphersuites(tls_conf, ids, nids);
8697+}
8698+
8699+
8700+__attribute_noinline__
8701+static int tls_mbedtls_set_item(char **config_item, const char *item)
8702+{
8703+ os_free(*config_item);
8704+ *config_item = NULL;
8705+ return item ? (*config_item = os_strdup(item)) != NULL : 1;
8706+}
8707+
8708+
8709+static int tls_connection_set_subject_match(struct tls_conf *tls_conf,
8710+ const struct tls_connection_params *params)
8711+{
8712+ int rc = 1;
8713+ rc &= tls_mbedtls_set_item(&tls_conf->subject_match,
8714+ params->subject_match);
8715+ rc &= tls_mbedtls_set_item(&tls_conf->altsubject_match,
8716+ params->altsubject_match);
8717+ rc &= tls_mbedtls_set_item(&tls_conf->suffix_match,
8718+ params->suffix_match);
8719+ rc &= tls_mbedtls_set_item(&tls_conf->domain_match,
8720+ params->domain_match);
8721+ rc &= tls_mbedtls_set_item(&tls_conf->check_cert_subject,
8722+ params->check_cert_subject);
8723+ return rc;
8724+}
8725+
8726+
8727+/* duplicated in crypto_mbedtls.c:crypto_mbedtls_readfile()*/
8728+__attribute_noinline__
8729+static int tls_mbedtls_readfile(const char *path, u8 **buf, size_t *n)
8730+{
8731+ #if 0 /* #ifdef MBEDTLS_FS_IO */
8732+ /*(includes +1 for '\0' needed by mbedtls PEM parsing funcs)*/
8733+ if (mbedtls_pk_load_file(path, (unsigned char **)buf, n) != 0) {
8734+ wpa_printf(MSG_ERROR, "error: mbedtls_pk_load_file %s", path);
8735+ return -1;
8736+ }
8737+ #else
8738+ /*(use os_readfile() so that we can use os_free()
8739+ *(if we use mbedtls_pk_load_file() above, macros prevent calling free()
8740+ * directly #if defined(OS_REJECT_C_LIB_FUNCTIONS) and calling os_free()
8741+ * on buf aborts in tests if buf not allocated via os_malloc())*/
8742+ *buf = (u8 *)os_readfile(path, n);
8743+ if (!*buf) {
8744+ wpa_printf(MSG_ERROR, "error: os_readfile %s", path);
8745+ return -1;
8746+ }
8747+ u8 *buf0 = os_realloc(*buf, *n+1);
8748+ if (!buf0) {
8749+ bin_clear_free(*buf, *n);
8750+ *buf = NULL;
8751+ return -1;
8752+ }
8753+ buf0[(*n)++] = '\0';
8754+ *buf = buf0;
8755+ #endif
8756+ return 0;
8757+}
8758+
8759+
8760+static int tls_mbedtls_set_crl(struct tls_conf *tls_conf, const u8 *data, size_t len)
8761+{
8762+ /* do not use mbedtls_x509_crl_parse() on PEM unless it contains CRL */
8763+ if (len && data[len-1] == '\0'
8764+ && NULL == os_strstr((const char *)data,"-----BEGIN X509 CRL-----")
8765+ && tls_mbedtls_data_is_pem(data))
8766+ return 0;
8767+
8768+ mbedtls_x509_crl crl;
8769+ mbedtls_x509_crl_init(&crl);
8770+ int rc = mbedtls_x509_crl_parse(&crl, data, len);
8771+ if (rc < 0) {
8772+ mbedtls_x509_crl_free(&crl);
8773+ return rc == MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ? 0 : rc;
8774+ }
8775+
8776+ mbedtls_x509_crl *crl_new = os_malloc(sizeof(crl));
8777+ if (crl_new == NULL) {
8778+ mbedtls_x509_crl_free(&crl);
8779+ return MBEDTLS_ERR_X509_ALLOC_FAILED;
8780+ }
8781+ os_memcpy(crl_new, &crl, sizeof(crl));
8782+
8783+ mbedtls_x509_crl *crl_old = tls_conf->crl;
8784+ tls_conf->crl = crl_new;
8785+ if (crl_old) {
8786+ mbedtls_x509_crl_free(crl_old);
8787+ os_free(crl_old);
8788+ }
8789+ return 0;
8790+}
8791+
8792+
8793+static int tls_mbedtls_set_ca(struct tls_conf *tls_conf, u8 *data, size_t len)
8794+{
8795+ /* load crt struct onto stack and then copy into tls_conf in
8796+ * order to preserve existing tls_conf value if error occurs
8797+ *
8798+ * hostapd is not threaded, or else should allocate memory and swap in
8799+ * pointer reduce race condition. (If threaded, would also need to
8800+ * keep reference count of use to avoid freeing while still in use.) */
8801+
8802+ mbedtls_x509_crt crt;
8803+ mbedtls_x509_crt_init(&crt);
8804+ int rc = mbedtls_x509_crt_parse(&crt, data, len);
8805+ if (rc < 0) {
8806+ mbedtls_x509_crt_free(&crt);
8807+ return rc;
8808+ }
8809+
8810+ mbedtls_x509_crt_free(&tls_conf->ca_cert);
8811+ os_memcpy(&tls_conf->ca_cert, &crt, sizeof(crt));
8812+ return 0;
8813+}
8814+
8815+
8816+static int tls_mbedtls_set_ca_and_crl(struct tls_conf *tls_conf, const char *ca_cert_file)
8817+{
8818+ size_t len;
8819+ u8 *data;
8820+ if (tls_mbedtls_readfile(ca_cert_file, &data, &len))
8821+ return -1;
8822+
8823+ int rc;
8824+ if (0 == (rc = tls_mbedtls_set_ca(tls_conf, data, len))
8825+ && (!tls_mbedtls_data_is_pem(data) /*skip parse for CRL if not PEM*/
8826+ || 0 == (rc = tls_mbedtls_set_crl(tls_conf, data, len)))) {
8827+ mbedtls_ssl_conf_ca_chain(&tls_conf->conf,
8828+ &tls_conf->ca_cert,
8829+ tls_conf->crl);
8830+ }
8831+ else {
8832+ elog(rc, __func__);
8833+ emsg(MSG_ERROR, ca_cert_file);
8834+ }
8835+
8836+ forced_memzero(data, len);
8837+ os_free(data);
8838+ return rc;
8839+}
8840+
8841+
8842+static void tls_mbedtls_refresh_crl(void)
8843+{
8844+ /* check for CRL refresh
8845+ * continue even if error occurs; continue with previous cert, CRL */
8846+ unsigned int crl_reload_interval = tls_ctx_global.crl_reload_interval;
8847+ const char *ca_cert_file = tls_ctx_global.ca_cert_file;
8848+ if (!crl_reload_interval || !ca_cert_file)
8849+ return;
8850+
8851+ struct os_reltime *previous = &tls_ctx_global.crl_reload_previous;
8852+ struct os_reltime now;
8853+ if (os_get_reltime(&now) != 0
8854+ || !os_reltime_expired(&now, previous, crl_reload_interval))
8855+ return;
8856+
8857+ /* Note: modifying global state is not thread-safe
8858+ * if in use by existing connections
8859+ *
8860+ * src/utils/os.h does not provide a portable stat()
8861+ * or else it would be a good idea to check mtime and size,
8862+ * and avoid reloading if file has not changed */
8863+
8864+ if (tls_mbedtls_set_ca_and_crl(tls_ctx_global.tls_conf, ca_cert_file) == 0)
8865+ *previous = now;
8866+}
8867+
8868+
8869+static int tls_mbedtls_set_ca_cert(struct tls_conf *tls_conf,
8870+ const struct tls_connection_params *params)
8871+{
8872+ if (params->ca_cert) {
8873+ if (os_strncmp(params->ca_cert, "probe://", 8) == 0) {
8874+ tls_conf->ca_cert_probe = 1;
8875+ tls_conf->has_ca_cert = 1;
8876+ return 0;
8877+ }
8878+
8879+ if (os_strncmp(params->ca_cert, "hash://", 7) == 0) {
8880+ const char *pos = params->ca_cert + 7;
8881+ if (os_strncmp(pos, "server/sha256/", 14) != 0) {
8882+ emsg(MSG_ERROR, "unsupported ca_cert hash value");
8883+ return -1;
8884+ }
8885+ pos += 14;
8886+ if (os_strlen(pos) != SHA256_DIGEST_LENGTH*2) {
8887+ emsg(MSG_ERROR, "unexpected ca_cert hash length");
8888+ return -1;
8889+ }
8890+ if (hexstr2bin(pos, tls_conf->ca_cert_hash,
8891+ SHA256_DIGEST_LENGTH) < 0) {
8892+ emsg(MSG_ERROR, "invalid ca_cert hash value");
8893+ return -1;
8894+ }
8895+ emsg(MSG_DEBUG, "checking only server certificate match");
8896+ tls_conf->verify_depth0_only = 1;
8897+ tls_conf->has_ca_cert = 1;
8898+ return 0;
8899+ }
8900+
8901+ if (tls_mbedtls_set_ca_and_crl(tls_conf, params->ca_cert) != 0)
8902+ return -1;
8903+ }
8904+ if (params->ca_cert_blob) {
8905+ size_t len = params->ca_cert_blob_len;
8906+ int is_pem = tls_mbedtls_data_is_pem(params->ca_cert_blob);
8907+ if (len && params->ca_cert_blob[len-1] != '\0' && is_pem)
8908+ ++len; /*(include '\0' in len for PEM)*/
8909+ int ret = mbedtls_x509_crt_parse(&tls_conf->ca_cert,
8910+ params->ca_cert_blob, len);
8911+ if (ret != 0) {
8912+ elog(ret, "mbedtls_x509_crt_parse");
8913+ return -1;
8914+ }
8915+ if (is_pem) { /*(ca_cert_blob in DER format contains ca cert only)*/
8916+ ret = tls_mbedtls_set_crl(tls_conf, params->ca_cert_blob, len);
8917+ if (ret != 0) {
8918+ elog(ret, "mbedtls_x509_crl_parse");
8919+ return -1;
8920+ }
8921+ }
8922+ }
8923+
8924+ if (mbedtls_x509_time_is_future(&tls_conf->ca_cert.valid_from)
8925+ || mbedtls_x509_time_is_past(&tls_conf->ca_cert.valid_to)) {
8926+ emsg(MSG_WARNING, "ca_cert expired or not yet valid");
8927+ if (params->ca_cert)
8928+ emsg(MSG_WARNING, params->ca_cert);
8929+ }
8930+
8931+ tls_conf->has_ca_cert = 1;
8932+ return 0;
8933+}
8934+
8935+
8936+static int tls_mbedtls_set_certs(struct tls_conf *tls_conf,
8937+ const struct tls_connection_params *params)
8938+{
8939+ int ret;
8940+
8941+ if (params->ca_cert || params->ca_cert_blob) {
8942+ if (tls_mbedtls_set_ca_cert(tls_conf, params) != 0)
8943+ return -1;
8944+ }
8945+ else if (params->ca_path) {
8946+ emsg(MSG_INFO, "ca_path support not implemented");
8947+ return -1;
8948+ }
8949+
8950+ if (!tls_conf->has_ca_cert)
8951+ mbedtls_ssl_conf_authmode(&tls_conf->conf, MBEDTLS_SSL_VERIFY_NONE);
8952+ else {
8953+ /* Initial setting: REQUIRED for client, OPTIONAL for server
8954+ * (see also tls_connection_set_verify()) */
8955+ tls_conf->verify_peer = (tls_ctx_global.tls_conf == NULL);
8956+ int authmode = tls_conf->verify_peer
8957+ ? MBEDTLS_SSL_VERIFY_REQUIRED
8958+ : MBEDTLS_SSL_VERIFY_OPTIONAL;
8959+ mbedtls_ssl_conf_authmode(&tls_conf->conf, authmode);
8960+ mbedtls_ssl_conf_ca_chain(&tls_conf->conf,
8961+ &tls_conf->ca_cert,
8962+ tls_conf->crl);
8963+
8964+ if (!tls_connection_set_subject_match(tls_conf, params))
8965+ return -1;
8966+ }
8967+
8968+ if (params->client_cert2) /*(yes, server_cert2 in msg below)*/
8969+ emsg(MSG_INFO, "server_cert2 support not implemented");
8970+
8971+ if (params->client_cert) {
8972+ size_t len;
8973+ u8 *data;
8974+ if (tls_mbedtls_readfile(params->client_cert, &data, &len))
8975+ return -1;
8976+ ret = mbedtls_x509_crt_parse(&tls_conf->client_cert, data, len);
8977+ forced_memzero(data, len);
8978+ os_free(data);
8979+ }
8980+ if (params->client_cert_blob) {
8981+ size_t len = params->client_cert_blob_len;
8982+ if (len && params->client_cert_blob[len-1] != '\0'
8983+ && tls_mbedtls_data_is_pem(params->client_cert_blob))
8984+ ++len; /*(include '\0' in len for PEM)*/
8985+ ret = mbedtls_x509_crt_parse(&tls_conf->client_cert,
8986+ params->client_cert_blob, len);
8987+ }
8988+ if (params->client_cert || params->client_cert_blob) {
8989+ if (ret < 0) {
8990+ elog(ret, "mbedtls_x509_crt_parse");
8991+ if (params->client_cert)
8992+ emsg(MSG_ERROR, params->client_cert);
8993+ return -1;
8994+ }
8995+ if (mbedtls_x509_time_is_future(&tls_conf->client_cert.valid_from)
8996+ || mbedtls_x509_time_is_past(&tls_conf->client_cert.valid_to)) {
8997+ emsg(MSG_WARNING, "cert expired or not yet valid");
8998+ if (params->client_cert)
8999+ emsg(MSG_WARNING, params->client_cert);
9000+ }
9001+ tls_conf->has_client_cert = 1;
9002+ }
9003+
9004+ if (params->private_key || params->private_key_blob) {
9005+ size_t len = params->private_key_blob_len;
9006+ u8 *data;
9007+ *(const u8 **)&data = params->private_key_blob;
9008+ if (len && data[len-1] != '\0' && tls_mbedtls_data_is_pem(data))
9009+ ++len; /*(include '\0' in len for PEM)*/
9010+ if (params->private_key
9011+ && tls_mbedtls_readfile(params->private_key, &data, &len)) {
9012+ return -1;
9013+ }
9014+ const char *pwd = params->private_key_passwd;
9015+ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
9016+ ret = mbedtls_pk_parse_key(&tls_conf->private_key,
9017+ data, len,
9018+ (const unsigned char *)pwd,
9019+ pwd ? os_strlen(pwd) : 0,
9020+ mbedtls_ctr_drbg_random,
9021+ tls_ctx_global.ctr_drbg);
9022+ #else
9023+ ret = mbedtls_pk_parse_key(&tls_conf->private_key,
9024+ data, len,
9025+ (const unsigned char *)pwd,
9026+ pwd ? os_strlen(pwd) : 0);
9027+ #endif
9028+ if (params->private_key) {
9029+ forced_memzero(data, len);
9030+ os_free(data);
9031+ }
9032+ if (ret < 0) {
9033+ elog(ret, "mbedtls_pk_parse_key");
9034+ return -1;
9035+ }
9036+ tls_conf->has_private_key = 1;
9037+ }
9038+
9039+ if (tls_conf->has_client_cert && tls_conf->has_private_key) {
9040+ ret = mbedtls_ssl_conf_own_cert(
9041+ &tls_conf->conf, &tls_conf->client_cert, &tls_conf->private_key);
9042+ if (ret < 0) {
9043+ elog(ret, "mbedtls_ssl_conf_own_cert");
9044+ return -1;
9045+ }
9046+ }
9047+
9048+ return 0;
9049+}
9050+
9051+
9052+/* mbedtls_x509_crt_profile_suiteb plus rsa_min_bitlen 2048 */
9053+/* (reference: see also mbedtls_x509_crt_profile_next) */
9054+/* ??? should permit SHA-512, too, and additional curves ??? */
9055+static const mbedtls_x509_crt_profile tls_mbedtls_crt_profile_suiteb128 =
9056+{
9057+ /* Only SHA-256 and 384 */
9058+ MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
9059+ MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ),
9060+ /* Only ECDSA */
9061+ MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ) |
9062+ MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECKEY ),
9063+#if defined(MBEDTLS_ECP_C)
9064+ /* Only NIST P-256 and P-384 */
9065+ MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) |
9066+ MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ),
9067+#else
9068+ 0,
9069+#endif
9070+ 2048,
9071+};
9072+
9073+
9074+/* stricter than mbedtls_x509_crt_profile_suiteb */
9075+/* (reference: see also mbedtls_x509_crt_profile_next) */
9076+/* ??? should permit SHA-512, too, and additional curves ??? */
9077+static const mbedtls_x509_crt_profile tls_mbedtls_crt_profile_suiteb192 =
9078+{
9079+ /* Only SHA-384 */
9080+ MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ),
9081+ /* Only ECDSA */
9082+ MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ) |
9083+ MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECKEY ),
9084+#if defined(MBEDTLS_ECP_C)
9085+ /* Only NIST P-384 */
9086+ MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ),
9087+#else
9088+ 0,
9089+#endif
9090+ 3072,
9091+};
9092+
9093+
9094+/* stricter than mbedtls_x509_crt_profile_suiteb except allow any PK alg */
9095+/* (reference: see also mbedtls_x509_crt_profile_next) */
9096+/* ??? should permit SHA-512, too, and additional curves ??? */
9097+static const mbedtls_x509_crt_profile tls_mbedtls_crt_profile_suiteb192_anypk =
9098+{
9099+ /* Only SHA-384 */
9100+ MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ),
9101+ 0xFFFFFFF, /* Any PK alg */
9102+#if defined(MBEDTLS_ECP_C)
9103+ /* Only NIST P-384 */
9104+ MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ),
9105+#else
9106+ 0,
9107+#endif
9108+ 3072,
9109+};
9110+
9111+
9112+static int tls_mbedtls_set_params(struct tls_conf *tls_conf,
9113+ const struct tls_connection_params *params)
9114+{
9115+ tls_conf->flags = params->flags;
9116+
9117+ if (tls_conf->flags & TLS_CONN_REQUIRE_OCSP_ALL) {
9118+ emsg(MSG_INFO, "ocsp=3 not supported");
9119+ return -1;
9120+ }
9121+
9122+ if (tls_conf->flags & TLS_CONN_REQUIRE_OCSP) {
9123+ emsg(MSG_INFO, "ocsp not supported");
9124+ return -1;
9125+ }
9126+
9127+ int suiteb128 = 0;
9128+ int suiteb192 = 0;
9129+ if (params->openssl_ciphers) {
9130+ if (os_strcmp(params->openssl_ciphers, "SUITEB192") == 0) {
9131+ suiteb192 = 1;
9132+ tls_conf->flags |= TLS_CONN_SUITEB;
9133+ }
9134+ if (os_strcmp(params->openssl_ciphers, "SUITEB128") == 0) {
9135+ suiteb128 = 1;
9136+ tls_conf->flags |= TLS_CONN_SUITEB;
9137+ }
9138+ }
9139+
9140+ int ret = mbedtls_ssl_config_defaults(
9141+ &tls_conf->conf, tls_ctx_global.tls_conf ? MBEDTLS_SSL_IS_SERVER
9142+ : MBEDTLS_SSL_IS_CLIENT,
9143+ MBEDTLS_SSL_TRANSPORT_STREAM,
9144+ (tls_conf->flags & TLS_CONN_SUITEB) ? MBEDTLS_SSL_PRESET_SUITEB
9145+ : MBEDTLS_SSL_PRESET_DEFAULT);
9146+ if (ret != 0) {
9147+ elog(ret, "mbedtls_ssl_config_defaults");
9148+ return -1;
9149+ }
9150+
9151+ if (suiteb128) {
9152+ mbedtls_ssl_conf_cert_profile(&tls_conf->conf,
9153+ &tls_mbedtls_crt_profile_suiteb128);
9154+ mbedtls_ssl_conf_dhm_min_bitlen(&tls_conf->conf, 2048);
9155+ }
9156+ else if (suiteb192) {
9157+ mbedtls_ssl_conf_cert_profile(&tls_conf->conf,
9158+ &tls_mbedtls_crt_profile_suiteb192);
9159+ mbedtls_ssl_conf_dhm_min_bitlen(&tls_conf->conf, 3072);
9160+ }
9161+ else if (tls_conf->flags & TLS_CONN_SUITEB) {
9162+ /* treat as suiteb192 while allowing any PK algorithm */
9163+ mbedtls_ssl_conf_cert_profile(&tls_conf->conf,
9164+ &tls_mbedtls_crt_profile_suiteb192_anypk);
9165+ mbedtls_ssl_conf_dhm_min_bitlen(&tls_conf->conf, 3072);
9166+ }
9167+
9168+ tls_mbedtls_set_allowed_tls_vers(tls_conf, &tls_conf->conf);
9169+ ret = tls_mbedtls_set_certs(tls_conf, params);
9170+ if (ret != 0)
9171+ return -1;
9172+
9173+ if (params->dh_file
9174+ && !tls_mbedtls_set_dhparams(tls_conf, params->dh_file)) {
9175+ return -1;
9176+ }
9177+
9178+ if (params->openssl_ecdh_curves
9179+ && !tls_mbedtls_set_curves(tls_conf, params->openssl_ecdh_curves)) {
9180+ return -1;
9181+ }
9182+
9183+ if (params->openssl_ciphers) {
9184+ if (!tls_mbedtls_set_ciphers(tls_conf, params->openssl_ciphers))
9185+ return -1;
9186+ }
9187+ else if (tls_conf->flags & TLS_CONN_SUITEB) {
9188+ /* special-case a select set of ciphers for hwsim tests */
9189+ if (!tls_mbedtls_set_ciphers(tls_conf,
9190+ (tls_conf->flags & TLS_CONN_SUITEB_NO_ECDH)
9191+ ? "DHE-RSA-AES256-GCM-SHA384"
9192+ : "ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384"))
9193+ return -1;
9194+ }
9195+
9196+ return 0;
9197+}
9198+
9199+
9200+int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
9201+ const struct tls_connection_params *params)
9202+{
9203+ if (conn == NULL || params == NULL)
9204+ return -1;
9205+
9206+ tls_conf_deinit(conn->tls_conf);
9207+ struct tls_conf *tls_conf = conn->tls_conf = tls_conf_init(tls_ctx);
9208+ if (tls_conf == NULL)
9209+ return -1;
9210+
9211+ if (tls_ctx_global.tls_conf) {
9212+ tls_conf->check_crl = tls_ctx_global.tls_conf->check_crl;
9213+ tls_conf->check_crl_strict = tls_ctx_global.tls_conf->check_crl_strict;
9214+ /*(tls_openssl.c inherits check_cert_subject from global conf)*/
9215+ if (tls_ctx_global.tls_conf->check_cert_subject) {
9216+ tls_conf->check_cert_subject =
9217+ os_strdup(tls_ctx_global.tls_conf->check_cert_subject);
9218+ if (tls_conf->check_cert_subject == NULL)
9219+ return -1;
9220+ }
9221+ }
9222+
9223+ if (tls_mbedtls_set_params(tls_conf, params) != 0)
9224+ return -1;
9225+ conn->verify_peer = tls_conf->verify_peer;
9226+
9227+ return tls_mbedtls_ssl_setup(conn);
9228+}
9229+
9230+
9231+#ifdef TLS_MBEDTLS_SESSION_TICKETS
9232+
9233+static int tls_mbedtls_clienthello_session_ticket_prep (struct tls_connection *conn,
9234+ const u8 *data, size_t len)
9235+{
9236+ if (conn->tls_conf->flags & TLS_CONN_DISABLE_SESSION_TICKET)
9237+ return -1;
9238+ if (conn->clienthello_session_ticket)
9239+ tls_connection_deinit_clienthello_session_ticket(conn);
9240+ if (len) {
9241+ conn->clienthello_session_ticket = mbedtls_calloc(1, len);
9242+ if (conn->clienthello_session_ticket == NULL)
9243+ return -1;
9244+ conn->clienthello_session_ticket_len = len;
9245+ os_memcpy(conn->clienthello_session_ticket, data, len);
9246+ }
9247+ return 0;
9248+}
9249+
9250+
9251+static void tls_mbedtls_clienthello_session_ticket_set (struct tls_connection *conn)
9252+{
9253+ mbedtls_ssl_session *sess = conn->ssl.MBEDTLS_PRIVATE(session_negotiate);
9254+ if (sess->MBEDTLS_PRIVATE(ticket)) {
9255+ mbedtls_platform_zeroize(sess->MBEDTLS_PRIVATE(ticket),
9256+ sess->MBEDTLS_PRIVATE(ticket_len));
9257+ mbedtls_free(sess->MBEDTLS_PRIVATE(ticket));
9258+ }
9259+ sess->MBEDTLS_PRIVATE(ticket) = conn->clienthello_session_ticket;
9260+ sess->MBEDTLS_PRIVATE(ticket_len) = conn->clienthello_session_ticket_len;
9261+ sess->MBEDTLS_PRIVATE(ticket_lifetime) = 86400;/* XXX: can hint be 0? */
9262+
9263+ conn->clienthello_session_ticket = NULL;
9264+ conn->clienthello_session_ticket_len = 0;
9265+}
9266+
9267+
9268+static int tls_mbedtls_ssl_ticket_write(void *p_ticket,
9269+ const mbedtls_ssl_session *session,
9270+ unsigned char *start,
9271+ const unsigned char *end,
9272+ size_t *tlen,
9273+ uint32_t *lifetime)
9274+{
9275+ struct tls_connection *conn = p_ticket;
9276+ if (conn && conn->session_ticket_cb) {
9277+ /* see tls_mbedtls_clienthello_session_ticket_prep() */
9278+ /* see tls_mbedtls_clienthello_session_ticket_set() */
9279+ return 0;
9280+ }
9281+
9282+ return mbedtls_ssl_ticket_write(&tls_ctx_global.ticket_ctx,
9283+ session, start, end, tlen, lifetime);
9284+}
9285+
9286+
9287+static int tls_mbedtls_ssl_ticket_parse(void *p_ticket,
9288+ mbedtls_ssl_session *session,
9289+ unsigned char *buf,
9290+ size_t len)
9291+{
9292+ /* XXX: TODO: not implemented in client;
9293+ * mbedtls_ssl_conf_session_tickets_cb() callbacks only for TLS server*/
9294+
9295+ if (len == 0)
9296+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
9297+
9298+ struct tls_connection *conn = p_ticket;
9299+ if (conn && conn->session_ticket_cb) {
9300+ /* XXX: have random and secret been initialized yet?
9301+ * or must keys first be exported?
9302+ * EAP-FAST uses all args, EAP-TEAP only uses secret */
9303+ struct tls_random data;
9304+ if (tls_connection_get_random(NULL, conn, &data) != 0)
9305+ return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
9306+ int ret =
9307+ conn->session_ticket_cb(conn->session_ticket_cb_ctx,
9308+ buf, len,
9309+ data.client_random,
9310+ data.server_random,
9311+ conn->expkey_secret);
9312+ if (ret == 1) {
9313+ conn->resumed = 1;
9314+ return 0;
9315+ }
9316+ emsg(MSG_ERROR, "EAP session ticket ext not implemented");
9317+ return MBEDTLS_ERR_SSL_INVALID_MAC;
9318+ /*(non-zero return used for mbedtls debug logging)*/
9319+ }
9320+
9321+ /* XXX: TODO always use tls_mbedtls_ssl_ticket_parse() for callback? */
9322+ int rc = mbedtls_ssl_ticket_parse(&tls_ctx_global.ticket_ctx,
9323+ session, buf, len);
9324+ if (conn)
9325+ conn->resumed = (rc == 0);
9326+ return rc;
9327+}
9328+
9329+#endif /* TLS_MBEDTLS_SESSION_TICKETS */
9330+
9331+
9332+__attribute_cold__
9333+int tls_global_set_params(void *tls_ctx,
9334+ const struct tls_connection_params *params)
9335+{
9336+ /* XXX: why might global_set_params be called more than once? */
9337+ if (tls_ctx_global.tls_conf)
9338+ tls_conf_deinit(tls_ctx_global.tls_conf);
9339+ tls_ctx_global.tls_conf = tls_conf_init(tls_ctx);
9340+ if (tls_ctx_global.tls_conf == NULL)
9341+ return -1;
9342+
9343+ #ifdef MBEDTLS_SSL_SESSION_TICKETS
9344+ #ifdef MBEDTLS_SSL_TICKET_C
9345+ if (!(params->flags & TLS_CONN_DISABLE_SESSION_TICKET))
9346+ #ifdef TLS_MBEDTLS_SESSION_TICKETS
9347+ mbedtls_ssl_conf_session_tickets_cb(&tls_ctx_global.tls_conf->conf,
9348+ tls_mbedtls_ssl_ticket_write,
9349+ tls_mbedtls_ssl_ticket_parse,
9350+ NULL);
9351+ #else
9352+ mbedtls_ssl_conf_session_tickets_cb(&tls_ctx_global.tls_conf->conf,
9353+ mbedtls_ssl_ticket_write,
9354+ mbedtls_ssl_ticket_parse,
9355+ &tls_ctx_global.ticket_ctx);
9356+ #endif
9357+ #endif
9358+ #endif
9359+
9360+ os_free(tls_ctx_global.ocsp_stapling_response);
9361+ tls_ctx_global.ocsp_stapling_response = NULL;
9362+ if (params->ocsp_stapling_response)
9363+ tls_ctx_global.ocsp_stapling_response =
9364+ os_strdup(params->ocsp_stapling_response);
9365+
9366+ os_free(tls_ctx_global.ca_cert_file);
9367+ tls_ctx_global.ca_cert_file = NULL;
9368+ if (params->ca_cert)
9369+ tls_ctx_global.ca_cert_file = os_strdup(params->ca_cert);
9370+ return tls_mbedtls_set_params(tls_ctx_global.tls_conf, params);
9371+}
9372+
9373+
9374+int tls_global_set_verify(void *tls_ctx, int check_crl, int strict)
9375+{
9376+ tls_ctx_global.tls_conf->check_crl = check_crl;
9377+ tls_ctx_global.tls_conf->check_crl_strict = strict; /*(time checks)*/
9378+ return 0;
9379+}
9380+
9381+
9382+int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn,
9383+ int verify_peer, unsigned int flags,
9384+ const u8 *session_ctx, size_t session_ctx_len)
9385+{
9386+ /*(EAP server-side calls this from eap_server_tls_ssl_init())*/
9387+ if (conn == NULL)
9388+ return -1;
9389+
9390+ conn->tls_conf->flags |= flags;/* TODO: reprocess flags, if necessary */
9391+
9392+ int authmode;
9393+ switch (verify_peer) {
9394+ case 2: authmode = MBEDTLS_SSL_VERIFY_OPTIONAL; break;/*(eap_teap_init())*/
9395+ case 1: authmode = MBEDTLS_SSL_VERIFY_REQUIRED; break;
9396+ default: authmode = MBEDTLS_SSL_VERIFY_NONE; break;
9397+ }
9398+ mbedtls_ssl_set_hs_authmode(&conn->ssl, authmode);
9399+
9400+ if ((conn->verify_peer = (authmode != MBEDTLS_SSL_VERIFY_NONE)))
9401+ mbedtls_ssl_set_verify(&conn->ssl, tls_mbedtls_verify_cb, conn);
9402+ else
9403+ mbedtls_ssl_set_verify(&conn->ssl, NULL, NULL);
9404+
9405+ return 0;
9406+}
9407+
9408+
9409+#if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
9410+static void tls_connection_export_keys_cb(
9411+ void *p_expkey, mbedtls_ssl_key_export_type secret_type,
9412+ const unsigned char *secret, size_t secret_len,
9413+ const unsigned char client_random[MBEDTLS_EXPKEY_RAND_LEN],
9414+ const unsigned char server_random[MBEDTLS_EXPKEY_RAND_LEN],
9415+ mbedtls_tls_prf_types tls_prf_type)
9416+{
9417+ struct tls_connection *conn = p_expkey;
9418+ conn->tls_prf_type = tls_prf_type;
9419+ if (!tls_prf_type)
9420+ return;
9421+ if (secret_len > sizeof(conn->expkey_secret)) {
9422+ emsg(MSG_ERROR, "tls_connection_export_keys_cb secret too long");
9423+ conn->tls_prf_type = MBEDTLS_SSL_TLS_PRF_NONE; /* 0 */
9424+ return;
9425+ }
9426+ conn->expkey_secret_len = secret_len;
9427+ os_memcpy(conn->expkey_secret, secret, secret_len);
9428+ os_memcpy(conn->expkey_randbytes,
9429+ client_random, MBEDTLS_EXPKEY_RAND_LEN);
9430+ os_memcpy(conn->expkey_randbytes + MBEDTLS_EXPKEY_RAND_LEN,
9431+ server_random, MBEDTLS_EXPKEY_RAND_LEN);
9432+}
9433+#elif MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */
9434+static int tls_connection_export_keys_cb(
9435+ void *p_expkey,
9436+ const unsigned char *ms,
9437+ const unsigned char *kb,
9438+ size_t maclen,
9439+ size_t keylen,
9440+ size_t ivlen,
9441+ const unsigned char client_random[MBEDTLS_EXPKEY_RAND_LEN],
9442+ const unsigned char server_random[MBEDTLS_EXPKEY_RAND_LEN],
9443+ mbedtls_tls_prf_types tls_prf_type )
9444+{
9445+ struct tls_connection *conn = p_expkey;
9446+ conn->tls_prf_type = tls_prf_type;
9447+ if (!tls_prf_type)
9448+ return -1; /*(return value ignored by mbedtls)*/
9449+ conn->expkey_keyblock_size = maclen + keylen + ivlen;
9450+ conn->expkey_secret_len = MBEDTLS_EXPKEY_FIXED_SECRET_LEN;
9451+ os_memcpy(conn->expkey_secret, ms, MBEDTLS_EXPKEY_FIXED_SECRET_LEN);
9452+ os_memcpy(conn->expkey_randbytes,
9453+ client_random, MBEDTLS_EXPKEY_RAND_LEN);
9454+ os_memcpy(conn->expkey_randbytes + MBEDTLS_EXPKEY_RAND_LEN,
9455+ server_random, MBEDTLS_EXPKEY_RAND_LEN);
9456+ return 0;
9457+}
9458+#endif
9459+
9460+
9461+int tls_connection_get_random(void *tls_ctx, struct tls_connection *conn,
9462+ struct tls_random *data)
9463+{
9464+ if (!conn || !conn->tls_prf_type)
9465+ return -1;
9466+ data->client_random = conn->expkey_randbytes;
9467+ data->client_random_len = MBEDTLS_EXPKEY_RAND_LEN;
9468+ data->server_random = conn->expkey_randbytes + MBEDTLS_EXPKEY_RAND_LEN;
9469+ data->server_random_len = MBEDTLS_EXPKEY_RAND_LEN;
9470+ return 0;
9471+}
9472+
9473+
9474+int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
9475+ const char *label, const u8 *context,
9476+ size_t context_len, u8 *out, size_t out_len)
9477+{
9478+ /* (EAP-PEAP EAP-TLS EAP-TTLS) */
9479+ #if MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */
9480+ return (conn && conn->established && conn->tls_prf_type)
9481+ ? mbedtls_ssl_tls_prf(conn->tls_prf_type,
9482+ conn->expkey_secret, conn->expkey_secret_len, label,
9483+ conn->expkey_randbytes,
9484+ sizeof(conn->expkey_randbytes), out, out_len)
9485+ : -1;
9486+ #else
9487+ /* not implemented here for mbedtls < 2.18.0 */
9488+ return -1;
9489+ #endif
9490+}
9491+
9492+
9493+#ifdef TLS_MBEDTLS_EAP_FAST
9494+
9495+#if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
9496+/* keyblock size info is not exposed in mbed TLS 3.0.0 */
9497+/* extracted from mbedtls library/ssl_tls.c:ssl_tls12_populate_transform() */
9498+#include <mbedtls/ssl_ciphersuites.h>
9499+#include <mbedtls/cipher.h>
9500+static size_t tls_mbedtls_ssl_keyblock_size (mbedtls_ssl_context *ssl)
9501+{
9502+ #if !defined(MBEDTLS_USE_PSA_CRYPTO) /* XXX: (not extracted for PSA crypto) */
9503+ #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
developer05f3b2b2024-08-19 19:17:34 +08009504+ if (mbedtls_ssl_get_version_number(ssl) == MBEDTLS_SSL_VERSION_TLS1_3)
developer66e89bc2024-04-23 14:50:01 +08009505+ return 0; /* (calculation not extracted) */
9506+ #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
9507+
9508+ int ciphersuite = mbedtls_ssl_get_ciphersuite_id_from_ssl(ssl);
9509+ const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
9510+ mbedtls_ssl_ciphersuite_from_id(ciphersuite);
9511+ if (ciphersuite_info == NULL)
9512+ return 0;
9513+
9514+ const mbedtls_cipher_info_t *cipher_info =
9515+ mbedtls_cipher_info_from_type(ciphersuite_info->MBEDTLS_PRIVATE(cipher));
9516+ if (cipher_info == NULL)
9517+ return 0;
9518+
9519+ #if MBEDTLS_VERSION_NUMBER >= 0x03010000 /* mbedtls 3.1.0 */
9520+ size_t keylen = mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8;
9521+ mbedtls_cipher_mode_t mode = mbedtls_cipher_info_get_mode(cipher_info);
9522+ #else
9523+ size_t keylen = cipher_info->MBEDTLS_PRIVATE(key_bitlen) / 8;
9524+ mbedtls_cipher_mode_t mode = cipher_info->MBEDTLS_PRIVATE(mode);
9525+ #endif
9526+ #if defined(MBEDTLS_GCM_C) || \
9527+ defined(MBEDTLS_CCM_C) || \
9528+ defined(MBEDTLS_CHACHAPOLY_C)
9529+ if (mode == MBEDTLS_MODE_GCM || mode == MBEDTLS_MODE_CCM)
9530+ return keylen + 4;
9531+ else if (mode == MBEDTLS_MODE_CHACHAPOLY)
9532+ return keylen + 12;
9533+ else
9534+ #endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */
9535+ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
9536+ {
9537+ const mbedtls_md_info_t *md_info =
9538+ mbedtls_md_info_from_type(ciphersuite_info->MBEDTLS_PRIVATE(mac));
9539+ if (md_info == NULL)
9540+ return 0;
9541+ size_t mac_key_len = mbedtls_md_get_size(md_info);
9542+ size_t ivlen = mbedtls_cipher_info_get_iv_size(cipher_info);
9543+ return keylen + mac_key_len + ivlen;
9544+ }
9545+ #endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
9546+ #endif /* !MBEDTLS_USE_PSA_CRYPTO *//* (not extracted for PSA crypto) */
9547+ return 0;
9548+}
9549+#endif /* MBEDTLS_VERSION_NUMBER >= 0x03000000 *//* mbedtls 3.0.0 */
9550+
9551+
9552+int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn,
9553+ u8 *out, size_t out_len)
9554+{
9555+ /* XXX: has export keys callback been run? */
9556+ if (!conn || !conn->tls_prf_type)
9557+ return -1;
9558+
9559+ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
9560+ conn->expkey_keyblock_size = tls_mbedtls_ssl_keyblock_size(&conn->ssl);
9561+ if (conn->expkey_keyblock_size == 0)
9562+ return -1;
9563+ #endif
9564+ size_t skip = conn->expkey_keyblock_size * 2;
9565+ unsigned char *tmp_out = os_malloc(skip + out_len);
9566+ if (!tmp_out)
9567+ return -1;
9568+
9569+ /* server_random and then client_random */
9570+ unsigned char seed[MBEDTLS_EXPKEY_RAND_LEN*2];
9571+ os_memcpy(seed, conn->expkey_randbytes + MBEDTLS_EXPKEY_RAND_LEN,
9572+ MBEDTLS_EXPKEY_RAND_LEN);
9573+ os_memcpy(seed + MBEDTLS_EXPKEY_RAND_LEN, conn->expkey_randbytes,
9574+ MBEDTLS_EXPKEY_RAND_LEN);
9575+
9576+ #if MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */
9577+ int ret = mbedtls_ssl_tls_prf(conn->tls_prf_type,
9578+ conn->expkey_secret, conn->expkey_secret_len,
9579+ "key expansion", seed, sizeof(seed),
9580+ tmp_out, skip + out_len);
9581+ if (ret == 0)
9582+ os_memcpy(out, tmp_out + skip, out_len);
9583+ #else
9584+ int ret = -1; /*(not reached if not impl; return -1 at top of func)*/
9585+ #endif
9586+
9587+ bin_clear_free(tmp_out, skip + out_len);
9588+ forced_memzero(seed, sizeof(seed));
9589+ return ret;
9590+}
9591+
9592+#endif /* TLS_MBEDTLS_EAP_FAST */
9593+
9594+
9595+__attribute_cold__
9596+static void tls_mbedtls_suiteb_handshake_alert (struct tls_connection *conn)
9597+{
9598+ /* tests/hwsim/test_suite_b.py test_suite_b_192_rsa_insufficient_dh */
9599+ if (!(conn->tls_conf->flags & TLS_CONN_SUITEB))
9600+ return;
9601+ if (tls_ctx_global.tls_conf) /*(is server; want issue event on client)*/
9602+ return;
9603+ #if 0
9604+ /*(info not available on client;
9605+ * mbed TLS library enforces dhm min bitlen in ServerKeyExchange)*/
9606+ if (MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 ==
9607+ #if MBEDTLS_VERSION_NUMBER < 0x03020000 /* mbedtls 3.2.0 */
9608+ mbedtls_ssl_get_ciphersuite_id_from_ssl(&conn->ssl)
9609+ #else
9610+ mbedtls_ssl_get_ciphersuite_id(
9611+ mbedtls_ssl_get_ciphersuite(&conn->ssl))
9612+ #endif
9613+ && mbedtls_mpi_size(&conn->tls_conf->conf.MBEDTLS_PRIVATE(dhm_P))
9614+ < 384 /*(3072/8)*/)
9615+ #endif
9616+ {
9617+ struct tls_config *init_conf = &tls_ctx_global.init_conf;
9618+ if (init_conf->event_cb) {
9619+ union tls_event_data ev;
9620+ os_memset(&ev, 0, sizeof(ev));
9621+ ev.alert.is_local = 1;
9622+ ev.alert.type = "fatal";
9623+ /*"internal error" string for tests/hwsim/test_suiteb.py */
9624+ ev.alert.description = "internal error: handshake failure";
9625+ /*ev.alert.description = "insufficient security";*/
9626+ init_conf->event_cb(init_conf->cb_ctx, TLS_ALERT, &ev);
9627+ }
9628+ }
9629+}
9630+
9631+
9632+struct wpabuf * tls_connection_handshake(void *tls_ctx,
9633+ struct tls_connection *conn,
9634+ const struct wpabuf *in_data,
9635+ struct wpabuf **appl_data)
9636+{
9637+ if (appl_data)
9638+ *appl_data = NULL;
9639+
9640+ if (in_data && wpabuf_len(in_data)) {
9641+ /*(unsure why tls_gnutls.c discards buffer contents; skip here)*/
9642+ if (conn->pull_buf && 0) /* disable; appears unwise */
9643+ tls_pull_buf_discard(conn, __func__);
9644+ if (!tls_pull_buf_append(conn, in_data))
9645+ return NULL;
9646+ }
9647+
9648+ if (conn->tls_conf == NULL) {
9649+ struct tls_connection_params params;
9650+ os_memset(&params, 0, sizeof(params));
9651+ params.openssl_ciphers =
9652+ tls_ctx_global.init_conf.openssl_ciphers;
9653+ params.flags = tls_ctx_global.tls_conf->flags;
9654+ if (tls_connection_set_params(tls_ctx, conn, &params) != 0)
9655+ return NULL;
9656+ }
9657+
9658+ if (conn->verify_peer) /*(call here might be redundant; nbd)*/
9659+ mbedtls_ssl_set_verify(&conn->ssl, tls_mbedtls_verify_cb, conn);
9660+
9661+ #ifdef TLS_MBEDTLS_SESSION_TICKETS
9662+ if (conn->clienthello_session_ticket)
9663+ /*(starting handshake for EAP-FAST and EAP-TEAP)*/
9664+ tls_mbedtls_clienthello_session_ticket_set(conn);
9665+
9666+ /* (not thread-safe due to need to set userdata 'conn' for callback) */
9667+ /* (unable to use mbedtls_ssl_set_user_data_p() with mbedtls 3.2.0+
9668+ * since ticket write and parse callbacks take (mbedtls_ssl_session *)
9669+ * param instead of (mbedtls_ssl_context *) param) */
9670+ if (conn->tls_conf->flags & TLS_CONN_DISABLE_SESSION_TICKET)
9671+ mbedtls_ssl_conf_session_tickets_cb(&conn->tls_conf->conf,
9672+ NULL, NULL, NULL);
9673+ else
9674+ mbedtls_ssl_conf_session_tickets_cb(&conn->tls_conf->conf,
9675+ tls_mbedtls_ssl_ticket_write,
9676+ tls_mbedtls_ssl_ticket_parse,
9677+ conn);
9678+ #endif
9679+
9680+ #if MBEDTLS_VERSION_NUMBER >= 0x03020000 /* mbedtls 3.2.0 */
9681+ int ret = mbedtls_ssl_handshake(&conn->ssl);
9682+ #else
9683+ int ret = 0;
9684+ while (conn->ssl.MBEDTLS_PRIVATE(state) != MBEDTLS_SSL_HANDSHAKE_OVER) {
9685+ ret = mbedtls_ssl_handshake_step(&conn->ssl);
9686+ if (ret != 0)
9687+ break;
9688+ }
9689+ #endif
9690+
9691+ #ifdef TLS_MBEDTLS_SESSION_TICKETS
9692+ mbedtls_ssl_conf_session_tickets_cb(&conn->tls_conf->conf,
9693+ tls_mbedtls_ssl_ticket_write,
9694+ tls_mbedtls_ssl_ticket_parse,
9695+ NULL);
9696+ #endif
9697+
9698+ switch (ret) {
9699+ case 0:
9700+ conn->established = 1;
9701+ if (conn->push_buf == NULL)
9702+ /* Need to return something to get final TLS ACK. */
9703+ conn->push_buf = wpabuf_alloc(0);
9704+
9705+ if (appl_data /*&& conn->pull_buf && wpabuf_len(conn->pull_buf)*/)
9706+ *appl_data = NULL; /* RFE: check for application data */
9707+ break;
9708+ case MBEDTLS_ERR_SSL_WANT_WRITE:
9709+ case MBEDTLS_ERR_SSL_WANT_READ:
9710+ case MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS:
9711+ case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS:
9712+ if (tls_ctx_global.tls_conf /*(is server)*/
9713+ && conn->established && conn->push_buf == NULL)
9714+ /* Need to return something to trigger completion of EAP-TLS. */
9715+ conn->push_buf = wpabuf_alloc(0);
9716+ break;
9717+ default:
9718+ ++conn->failed;
9719+ switch (ret) {
9720+ case MBEDTLS_ERR_SSL_CLIENT_RECONNECT:
9721+ case MBEDTLS_ERR_NET_CONN_RESET:
9722+ case MBEDTLS_ERR_NET_SEND_FAILED:
9723+ ++conn->write_alerts;
9724+ break;
9725+ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
9726+ case MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE:
9727+ #else
9728+ case MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE:
9729+ #endif
9730+ tls_mbedtls_suiteb_handshake_alert(conn);
9731+ /* fall through */
9732+ case MBEDTLS_ERR_NET_RECV_FAILED:
9733+ case MBEDTLS_ERR_SSL_CONN_EOF:
9734+ case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
9735+ case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE:
9736+ ++conn->read_alerts;
9737+ break;
9738+ default:
9739+ break;
9740+ }
9741+
9742+ ilog(ret, "mbedtls_ssl_handshake");
9743+ break;
9744+ }
9745+
9746+ struct wpabuf *out_data = conn->push_buf;
9747+ conn->push_buf = NULL;
9748+ return out_data;
9749+}
9750+
9751+
9752+struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
9753+ struct tls_connection *conn,
9754+ const struct wpabuf *in_data,
9755+ struct wpabuf **appl_data)
9756+{
9757+ conn->is_server = 1;
9758+ return tls_connection_handshake(tls_ctx, conn, in_data, appl_data);
9759+}
9760+
9761+
9762+struct wpabuf * tls_connection_encrypt(void *tls_ctx,
9763+ struct tls_connection *conn,
9764+ const struct wpabuf *in_data)
9765+{
9766+ int res = mbedtls_ssl_write(&conn->ssl,
9767+ wpabuf_head_u8(in_data), wpabuf_len(in_data));
9768+ if (res < 0) {
9769+ elog(res, "mbedtls_ssl_write");
9770+ return NULL;
9771+ }
9772+
9773+ struct wpabuf *buf = conn->push_buf;
9774+ conn->push_buf = NULL;
9775+ return buf;
9776+}
9777+
9778+
9779+struct wpabuf * tls_connection_decrypt(void *tls_ctx,
9780+ struct tls_connection *conn,
9781+ const struct wpabuf *in_data)
9782+{
9783+ int res;
9784+ struct wpabuf *out;
9785+
9786+ /*assert(in_data != NULL);*/
9787+ if (!tls_pull_buf_append(conn, in_data))
9788+ return NULL;
9789+
9790+ #if defined(MBEDTLS_ZLIB_SUPPORT) /* removed in mbedtls 3.x */
9791+ /* Add extra buffer space to handle the possibility of decrypted
9792+ * data being longer than input data due to TLS compression. */
9793+ out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
9794+ #else /* TLS compression is disabled in mbedtls 3.x */
9795+ out = wpabuf_alloc(wpabuf_len(in_data));
9796+ #endif
9797+ if (out == NULL)
9798+ return NULL;
9799+
9800+ res = mbedtls_ssl_read(&conn->ssl, wpabuf_mhead(out), wpabuf_size(out));
9801+ if (res < 0) {
9802+ #if 1 /*(seems like a different error if wpabuf_len(in_data) == 0)*/
9803+ if (res == MBEDTLS_ERR_SSL_WANT_READ)
9804+ return out;
9805+ #endif
9806+ elog(res, "mbedtls_ssl_read");
9807+ wpabuf_free(out);
9808+ return NULL;
9809+ }
9810+ wpabuf_put(out, res);
9811+
9812+ return out;
9813+}
9814+
9815+
9816+int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn)
9817+{
9818+ /* XXX: might need to detect if session resumed from TLS session ticket
9819+ * even if not special session ticket handling for EAP-FAST, EAP-TEAP */
9820+ /* (?ssl->handshake->resume during session ticket validation?) */
9821+ return conn && conn->resumed;
9822+}
9823+
9824+
9825+#ifdef TLS_MBEDTLS_EAP_FAST
9826+int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
9827+ u8 *ciphers)
9828+{
9829+ /* ciphers is list of TLS_CIPHER_* from hostap/src/crypto/tls.h */
9830+ int ids[7];
9831+ const int idsz = (int)sizeof(ids);
9832+ int nids = -1, id;
9833+ for ( ; *ciphers != TLS_CIPHER_NONE; ++ciphers) {
9834+ switch (*ciphers) {
9835+ case TLS_CIPHER_RC4_SHA:
9836+ #ifdef MBEDTLS_TLS_RSA_WITH_RC4_128_SHA
9837+ id = MBEDTLS_TLS_RSA_WITH_RC4_128_SHA;
9838+ break;
9839+ #else
9840+ continue; /*(not supported in mbedtls 3.x; ignore)*/
9841+ #endif
9842+ case TLS_CIPHER_AES128_SHA:
9843+ id = MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA;
9844+ break;
9845+ case TLS_CIPHER_RSA_DHE_AES128_SHA:
9846+ id = MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
9847+ break;
9848+ case TLS_CIPHER_ANON_DH_AES128_SHA:
9849+ continue; /*(not supported in mbedtls; ignore)*/
9850+ case TLS_CIPHER_RSA_DHE_AES256_SHA:
9851+ id = MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
9852+ break;
9853+ case TLS_CIPHER_AES256_SHA:
9854+ id = MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA;
9855+ break;
9856+ default:
9857+ return -1; /* should not happen */
9858+ }
9859+ if (++nids == idsz)
9860+ return -1; /* should not happen */
9861+ ids[nids] = id;
9862+ }
9863+ if (nids < 0)
9864+ return 0; /* nothing to do */
9865+ if (++nids == idsz)
9866+ return -1; /* should not happen */
9867+ ids[nids] = 0; /* terminate list */
9868+ ++nids;
9869+
9870+ return tls_mbedtls_set_ciphersuites(conn->tls_conf, ids, nids) ? 0 : -1;
9871+}
9872+#endif
9873+
9874+
9875+int tls_get_version(void *ssl_ctx, struct tls_connection *conn,
9876+ char *buf, size_t buflen)
9877+{
9878+ if (conn == NULL)
9879+ return -1;
9880+ os_strlcpy(buf, mbedtls_ssl_get_version(&conn->ssl), buflen);
9881+ return buf[0] != 'u' ? 0 : -1; /*(-1 if "unknown")*/
9882+}
9883+
9884+
9885+#ifdef TLS_MBEDTLS_EAP_TEAP
9886+u16 tls_connection_get_cipher_suite(struct tls_connection *conn)
9887+{
9888+ if (conn == NULL)
9889+ return 0;
9890+ return (u16)mbedtls_ssl_get_ciphersuite_id_from_ssl(&conn->ssl);
9891+}
9892+#endif
9893+
9894+
9895+int tls_get_cipher(void *tls_ctx, struct tls_connection *conn,
9896+ char *buf, size_t buflen)
9897+{
9898+ if (conn == NULL)
9899+ return -1;
9900+ const int id = mbedtls_ssl_get_ciphersuite_id_from_ssl(&conn->ssl);
9901+ return tls_mbedtls_translate_ciphername(id, buf, buflen) ? 0 : -1;
9902+}
9903+
9904+
9905+#ifdef TLS_MBEDTLS_SESSION_TICKETS
9906+
9907+int tls_connection_enable_workaround(void *tls_ctx,
9908+ struct tls_connection *conn)
9909+{
9910+ /* (see comment in src/eap_peer/eap_fast.c:eap_fast_init()) */
9911+ /* XXX: is there a relevant setting for this in mbed TLS? */
9912+ /* (do we even care that much about older CBC ciphers?) */
9913+ return 0;
9914+}
9915+
9916+
9917+int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn,
9918+ int ext_type, const u8 *data,
9919+ size_t data_len)
9920+{
9921+ /* (EAP-FAST and EAP-TEAP) */
9922+ if (ext_type == MBEDTLS_TLS_EXT_SESSION_TICKET) /*(ext_type == 35)*/
9923+ return tls_mbedtls_clienthello_session_ticket_prep(conn, data,
9924+ data_len);
9925+
9926+ return -1;
9927+}
9928+
9929+#endif /* TLS_MBEDTLS_SESSION_TICKETS */
9930+
9931+
9932+int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn)
9933+{
9934+ return conn ? conn->failed : -1;
9935+}
9936+
9937+
9938+int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn)
9939+{
9940+ return conn ? conn->read_alerts : -1;
9941+}
9942+
9943+
9944+int tls_connection_get_write_alerts(void *tls_ctx,
9945+ struct tls_connection *conn)
9946+{
9947+ return conn ? conn->write_alerts : -1;
9948+}
9949+
9950+
9951+#ifdef TLS_MBEDTLS_SESSION_TICKETS
9952+int tls_connection_set_session_ticket_cb(
9953+ void *tls_ctx, struct tls_connection *conn,
9954+ tls_session_ticket_cb cb, void *ctx)
9955+{
9956+ if (!(conn->tls_conf->flags & TLS_CONN_DISABLE_SESSION_TICKET)) {
9957+ /* (EAP-FAST and EAP-TEAP) */
9958+ conn->session_ticket_cb = cb;
9959+ conn->session_ticket_cb_ctx = ctx;
9960+ return 0;
9961+ }
9962+ return -1;
9963+}
9964+#endif
9965+
9966+
9967+int tls_get_library_version(char *buf, size_t buf_len)
9968+{
9969+ #ifndef MBEDTLS_VERSION_C
9970+ const char * const ver = "n/a";
9971+ #else
9972+ char ver[9];
9973+ mbedtls_version_get_string(ver);
9974+ #endif
9975+ return os_snprintf(buf, buf_len,
9976+ "mbed TLS build=" MBEDTLS_VERSION_STRING " run=%s", ver);
9977+}
9978+
9979+
9980+void tls_connection_set_success_data(struct tls_connection *conn,
9981+ struct wpabuf *data)
9982+{
9983+ wpabuf_free(conn->success_data);
9984+ conn->success_data = data;
9985+}
9986+
9987+
9988+void tls_connection_set_success_data_resumed(struct tls_connection *conn)
9989+{
9990+}
9991+
9992+
9993+const struct wpabuf *
9994+tls_connection_get_success_data(struct tls_connection *conn)
9995+{
9996+ return conn->success_data;
9997+}
9998+
9999+
10000+void tls_connection_remove_session(struct tls_connection *conn)
10001+{
10002+}
10003+
10004+
10005+#ifdef TLS_MBEDTLS_EAP_TEAP
10006+int tls_get_tls_unique(struct tls_connection *conn, u8 *buf, size_t max_len)
10007+{
10008+ #if defined(MBEDTLS_SSL_RENEGOTIATION) /* XXX: renegotiation or resumption? */
10009+ /* data from TLS handshake Finished message */
10010+ size_t verify_len = conn->ssl.MBEDTLS_PRIVATE(verify_data_len);
10011+ char *verify_data = (conn->is_server ^ conn->resumed)
10012+ ? conn->ssl.MBEDTLS_PRIVATE(peer_verify_data)
10013+ : conn->ssl.MBEDTLS_PRIVATE(own_verify_data);
10014+ if (verify_len && verify_len <= max_len) {
10015+ os_memcpy(buf, verify_data, verify_len);
10016+ return (int)verify_len;
10017+ }
10018+ #endif
10019+ return -1;
10020+}
10021+#endif
10022+
10023+
10024+__attribute_noinline__
10025+static void tls_mbedtls_set_peer_subject(struct tls_connection *conn, const mbedtls_x509_crt *crt)
10026+{
10027+ if (conn->peer_subject)
10028+ return;
10029+ char buf[MBEDTLS_X509_MAX_DN_NAME_SIZE*2];
10030+ int buflen = mbedtls_x509_dn_gets(buf, sizeof(buf), &crt->subject);
10031+ if (buflen >= 0 && (conn->peer_subject = os_malloc((size_t)buflen+1)))
10032+ os_memcpy(conn->peer_subject, buf, (size_t)buflen+1);
10033+}
10034+
10035+
10036+#ifdef TLS_MBEDTLS_EAP_TEAP
10037+const char * tls_connection_get_peer_subject(struct tls_connection *conn)
10038+{
10039+ if (!conn)
10040+ return NULL;
10041+ if (!conn->peer_subject) { /*(if not set during cert verify)*/
10042+ const mbedtls_x509_crt *peer_cert =
10043+ mbedtls_ssl_get_peer_cert(&conn->ssl);
10044+ if (peer_cert)
10045+ tls_mbedtls_set_peer_subject(conn, peer_cert);
10046+ }
10047+ return conn->peer_subject;
10048+}
10049+#endif
10050+
10051+
10052+#ifdef TLS_MBEDTLS_EAP_TEAP
10053+bool tls_connection_get_own_cert_used(struct tls_connection *conn)
10054+{
10055+ /* XXX: availability of cert does not necessary mean that client
10056+ * received certificate request from server and then sent cert.
10057+ * ? step handshake in tls_connection_handshake() looking for
10058+ * MBEDTLS_SSL_CERTIFICATE_REQUEST ? */
10059+ const struct tls_conf * const tls_conf = conn->tls_conf;
10060+ return (tls_conf->has_client_cert && tls_conf->has_private_key);
10061+}
10062+#endif
10063+
10064+
10065+#if defined(CONFIG_FIPS)
10066+#define TLS_MBEDTLS_CONFIG_FIPS
10067+#endif
10068+
10069+#if defined(CONFIG_SHA256)
10070+#define TLS_MBEDTLS_TLS_PRF_SHA256
10071+#endif
10072+
10073+#if defined(CONFIG_SHA384)
10074+#define TLS_MBEDTLS_TLS_PRF_SHA384
10075+#endif
10076+
10077+
10078+#ifndef TLS_MBEDTLS_CONFIG_FIPS
10079+#if defined(CONFIG_MODULE_TESTS)
10080+/* unused with CONFIG_TLS=mbedtls except in crypto_module_tests.c */
10081+#if MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */ \
10082+ && MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */
10083+/* sha1-tlsprf.c */
10084+#include "sha1.h"
10085+int tls_prf_sha1_md5(const u8 *secret, size_t secret_len, const char *label,
10086+ const u8 *seed, size_t seed_len, u8 *out, size_t outlen)
10087+{
10088+ return mbedtls_ssl_tls_prf(MBEDTLS_SSL_TLS_PRF_TLS1,
10089+ secret, secret_len, label,
10090+ seed, seed_len, out, outlen) ? -1 : 0;
10091+}
10092+#else
10093+#include "sha1-tlsprf.c" /* pull in hostap local implementation */
10094+#endif
10095+#endif
10096+#endif
10097+
10098+#ifdef TLS_MBEDTLS_TLS_PRF_SHA256
10099+/* sha256-tlsprf.c */
10100+#if MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */
10101+#include "sha256.h"
10102+int tls_prf_sha256(const u8 *secret, size_t secret_len, const char *label,
10103+ const u8 *seed, size_t seed_len, u8 *out, size_t outlen)
10104+{
10105+ return mbedtls_ssl_tls_prf(MBEDTLS_SSL_TLS_PRF_SHA256,
10106+ secret, secret_len, label,
10107+ seed, seed_len, out, outlen) ? -1 : 0;
10108+}
10109+#else
10110+#include "sha256-tlsprf.c" /* pull in hostap local implementation */
10111+#endif
10112+#endif
10113+
10114+#ifdef TLS_MBEDTLS_TLS_PRF_SHA384
10115+/* sha384-tlsprf.c */
10116+#if MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */
10117+#include "sha384.h"
10118+int tls_prf_sha384(const u8 *secret, size_t secret_len, const char *label,
10119+ const u8 *seed, size_t seed_len, u8 *out, size_t outlen)
10120+{
10121+ return mbedtls_ssl_tls_prf(MBEDTLS_SSL_TLS_PRF_SHA384,
10122+ secret, secret_len, label,
10123+ seed, seed_len, out, outlen) ? -1 : 0;
10124+}
10125+#else
10126+#include "sha384-tlsprf.c" /* pull in hostap local implementation */
10127+#endif
10128+#endif
10129+
10130+
10131+#if MBEDTLS_VERSION_NUMBER < 0x03020000 /* mbedtls 3.2.0 */
10132+#define mbedtls_x509_crt_has_ext_type(crt, ext_type) \
10133+ ((crt)->MBEDTLS_PRIVATE(ext_types) & (ext_type))
10134+#endif
10135+
10136+struct mlist { const char *p; size_t n; };
10137+
10138+
10139+static int
10140+tls_mbedtls_match_altsubject(mbedtls_x509_crt *crt, const char *match)
10141+{
10142+ /* RFE: this could be pre-parsed into structured data at config time */
10143+ struct mlist list[256]; /*(much larger than expected)*/
10144+ int nlist = 0;
10145+ if ( os_strncmp(match, "EMAIL:", 6) != 0
10146+ && os_strncmp(match, "DNS:", 4) != 0
10147+ && os_strncmp(match, "URI:", 4) != 0 ) {
10148+ wpa_printf(MSG_INFO, "MTLS: Invalid altSubjectName match '%s'", match);
10149+ return 0;
10150+ }
10151+ for (const char *s = match, *tok; *s; s = tok ? tok+1 : "") {
10152+ do { } while ((tok = os_strchr(s, ';'))
10153+ && os_strncmp(tok+1, "EMAIL:", 6) != 0
10154+ && os_strncmp(tok+1, "DNS:", 4) != 0
10155+ && os_strncmp(tok+1, "URI:", 4) != 0);
10156+ list[nlist].p = s;
10157+ list[nlist].n = tok ? (size_t)(tok - s) : os_strlen(s);
10158+ if (list[nlist].n && ++nlist == sizeof(list)/sizeof(*list)) {
10159+ wpa_printf(MSG_INFO, "MTLS: excessive altSubjectName match '%s'",
10160+ match);
10161+ break; /* truncate huge list and continue */
10162+ }
10163+ }
10164+
10165+ if (!mbedtls_x509_crt_has_ext_type(crt, MBEDTLS_X509_EXT_SUBJECT_ALT_NAME))
10166+ return 0;
10167+
10168+ const mbedtls_x509_sequence *cur = &crt->subject_alt_names;
10169+ for (; cur != NULL; cur = cur->next) {
10170+ const unsigned char san_type = (unsigned char)cur->buf.tag
10171+ & MBEDTLS_ASN1_TAG_VALUE_MASK;
10172+ char t;
10173+ size_t step = 4;
10174+ switch (san_type) { /* "EMAIL:" or "DNS:" or "URI:" */
10175+ case MBEDTLS_X509_SAN_RFC822_NAME: step = 6; t = 'E'; break;
10176+ case MBEDTLS_X509_SAN_DNS_NAME: t = 'D'; break;
10177+ case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: t = 'U'; break;
10178+ default: continue;
10179+ }
10180+
10181+ for (int i = 0; i < nlist; ++i) {
10182+ /* step over "EMAIL:" or "DNS:" or "URI:" in list[i].p */
10183+ /* Note: v is not '\0'-terminated, but is a known length vlen,
10184+ * so okay to pass to os_strncasecmp() even though not z-string */
10185+ if (cur->buf.len == list[i].n - step && t == *list[i].p
10186+ && 0 == os_strncasecmp((char *)cur->buf.p,
10187+ list[i].p+step, cur->buf.len)) {
10188+ return 1; /* match */
10189+ }
10190+ }
10191+ }
10192+ return 0; /* no match */
10193+}
10194+
10195+
10196+static int
10197+tls_mbedtls_match_suffix(const char *v, size_t vlen,
10198+ const struct mlist *list, int nlist, int full)
10199+{
10200+ /* Note: v is not '\0'-terminated, but is a known length vlen,
10201+ * so okay to pass to os_strncasecmp() even though not z-string */
10202+ for (int i = 0; i < nlist; ++i) {
10203+ size_t n = list[i].n;
10204+ if ((n == vlen || (n < vlen && v[vlen-n-1] == '.' && !full))
10205+ && 0 == os_strncasecmp(v+vlen-n, list[i].p, n))
10206+ return 1; /* match */
10207+ }
10208+ return 0; /* no match */
10209+}
10210+
10211+
10212+static int
10213+tls_mbedtls_match_suffixes(mbedtls_x509_crt *crt, const char *match, int full)
10214+{
10215+ /* RFE: this could be pre-parsed into structured data at config time */
10216+ struct mlist list[256]; /*(much larger than expected)*/
10217+ int nlist = 0;
10218+ for (const char *s = match, *tok; *s; s = tok ? tok+1 : "") {
10219+ tok = os_strchr(s, ';');
10220+ list[nlist].p = s;
10221+ list[nlist].n = tok ? (size_t)(tok - s) : os_strlen(s);
10222+ if (list[nlist].n && ++nlist == sizeof(list)/sizeof(*list)) {
10223+ wpa_printf(MSG_INFO, "MTLS: excessive suffix match '%s'", match);
10224+ break; /* truncate huge list and continue */
10225+ }
10226+ }
10227+
10228+ /* check subjectAltNames */
10229+ if (mbedtls_x509_crt_has_ext_type(crt, MBEDTLS_X509_EXT_SUBJECT_ALT_NAME)) {
10230+ const mbedtls_x509_sequence *cur = &crt->subject_alt_names;
10231+ for (; cur != NULL; cur = cur->next) {
10232+ const unsigned char san_type = (unsigned char)cur->buf.tag
10233+ & MBEDTLS_ASN1_TAG_VALUE_MASK;
10234+ if (san_type == MBEDTLS_X509_SAN_DNS_NAME
10235+ && tls_mbedtls_match_suffix((char *)cur->buf.p,
10236+ cur->buf.len,
10237+ list, nlist, full)) {
10238+ return 1; /* match */
10239+ }
10240+ }
10241+ }
10242+
10243+ /* check subject CN */
10244+ const mbedtls_x509_name *name = &crt->subject;
10245+ for (; name != NULL; name = name->next) {
10246+ if (name->oid.p && MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid) == 0)
10247+ break;
10248+ }
10249+ if (name && tls_mbedtls_match_suffix((char *)name->val.p, name->val.len,
10250+ list, nlist, full)) {
10251+ return 1; /* match */
10252+ }
10253+
10254+ return 0; /* no match */
10255+}
10256+
10257+
10258+static int
10259+tls_mbedtls_match_dn_field(mbedtls_x509_crt *crt, const char *match)
10260+{
10261+ /* RFE: this could be pre-parsed into structured data at config time */
10262+ struct mlistoid { const char *p; size_t n;
10263+ const char *oid; size_t olen;
10264+ int prefix; };
10265+ struct mlistoid list[32]; /*(much larger than expected)*/
10266+ int nlist = 0;
10267+ for (const char *s = match, *tok, *e; *s; s = tok ? tok+1 : "") {
10268+ tok = os_strchr(s, '/');
10269+ list[nlist].oid = NULL;
10270+ list[nlist].olen = 0;
10271+ list[nlist].n = tok ? (size_t)(tok - s) : os_strlen(s);
10272+ e = memchr(s, '=', list[nlist].n);
10273+ if (e == NULL) {
10274+ if (list[nlist].n == 0)
10275+ continue; /* skip consecutive, repeated '/' */
10276+ if (list[nlist].n == 1 && *s == '*') {
10277+ /* special-case "*" to match any OID and value */
10278+ s = e = "=*";
10279+ list[nlist].n = 2;
10280+ list[nlist].oid = "";
10281+ }
10282+ else {
10283+ wpa_printf(MSG_INFO,
10284+ "MTLS: invalid check_cert_subject '%s' missing '='",
10285+ match);
10286+ return 0;
10287+ }
10288+ }
10289+ switch (e - s) {
10290+ case 1:
10291+ if (*s == 'C') {
10292+ list[nlist].oid = MBEDTLS_OID_AT_COUNTRY;
10293+ list[nlist].olen = sizeof(MBEDTLS_OID_AT_COUNTRY)-1;
10294+ }
10295+ else if (*s == 'L') {
10296+ list[nlist].oid = MBEDTLS_OID_AT_LOCALITY;
10297+ list[nlist].olen = sizeof(MBEDTLS_OID_AT_LOCALITY)-1;
10298+ }
10299+ else if (*s == 'O') {
10300+ list[nlist].oid = MBEDTLS_OID_AT_ORGANIZATION;
10301+ list[nlist].olen = sizeof(MBEDTLS_OID_AT_ORGANIZATION)-1;
10302+ }
10303+ break;
10304+ case 2:
10305+ if (s[0] == 'C' && s[1] == 'N') {
10306+ list[nlist].oid = MBEDTLS_OID_AT_CN;
10307+ list[nlist].olen = sizeof(MBEDTLS_OID_AT_CN)-1;
10308+ }
10309+ else if (s[0] == 'S' && s[1] == 'T') {
10310+ list[nlist].oid = MBEDTLS_OID_AT_STATE;
10311+ list[nlist].olen = sizeof(MBEDTLS_OID_AT_STATE)-1;
10312+ }
10313+ else if (s[0] == 'O' && s[1] == 'U') {
10314+ list[nlist].oid = MBEDTLS_OID_AT_ORG_UNIT;
10315+ list[nlist].olen = sizeof(MBEDTLS_OID_AT_ORG_UNIT)-1;
10316+ }
10317+ break;
10318+ case 12:
10319+ if (os_memcmp(s, "emailAddress", 12) == 0) {
10320+ list[nlist].oid = MBEDTLS_OID_PKCS9_EMAIL;
10321+ list[nlist].olen = sizeof(MBEDTLS_OID_PKCS9_EMAIL)-1;
10322+ }
10323+ break;
10324+ default:
10325+ break;
10326+ }
10327+ if (list[nlist].oid == NULL) {
10328+ wpa_printf(MSG_INFO,
10329+ "MTLS: Unknown field in check_cert_subject '%s'",
10330+ match);
10331+ return 0;
10332+ }
10333+ list[nlist].n -= (size_t)(++e - s);
10334+ list[nlist].p = e;
10335+ if (list[nlist].n && e[list[nlist].n-1] == '*') {
10336+ --list[nlist].n;
10337+ list[nlist].prefix = 1;
10338+ }
10339+ /*(could easily add support for suffix matches if value begins with '*',
10340+ * but suffix match is not currently supported by other TLS modules)*/
10341+
10342+ if (list[nlist].n && ++nlist == sizeof(list)/sizeof(*list)) {
10343+ wpa_printf(MSG_INFO,
10344+ "MTLS: excessive check_cert_subject match '%s'",
10345+ match);
10346+ break; /* truncate huge list and continue */
10347+ }
10348+ }
10349+
10350+ /* each component in match string must match cert Subject in order listed
10351+ * The behavior below preserves ordering but is slightly different than
10352+ * the grossly inefficient contortions implemented in tls_openssl.c */
10353+ const mbedtls_x509_name *name = &crt->subject;
10354+ for (int i = 0; i < nlist; ++i) {
10355+ int found = 0;
10356+ for (; name != NULL && !found; name = name->next) {
10357+ if (!name->oid.p)
10358+ continue;
10359+ /* special-case "*" to match any OID and value */
10360+ if (list[i].olen == 0) {
10361+ found = 1;
10362+ continue;
10363+ }
10364+ /* perform equalent of !MBEDTLS_OID_CMP() with oid ptr and len */
10365+ if (list[i].olen != name->oid.len
10366+ || os_memcmp(list[i].oid, name->oid.p, name->oid.len) != 0)
10367+ continue;
10368+ /* Note: v is not '\0'-terminated, but is a known length vlen,
10369+ * so okay to pass to os_strncasecmp() even though not z-string */
10370+ if ((list[i].prefix
10371+ ? list[i].n <= name->val.len /* prefix match */
10372+ : list[i].n == name->val.len) /* full match */
10373+ && 0 == os_strncasecmp((char *)name->val.p,
10374+ list[i].p, list[i].n)) {
10375+ found = 1;
10376+ continue;
10377+ }
10378+ }
10379+ if (!found)
10380+ return 0; /* no match */
10381+ }
10382+ return 1; /* match */
10383+}
10384+
10385+
10386+__attribute_cold__
10387+static void
10388+tls_mbedtls_verify_fail_event (mbedtls_x509_crt *crt, int depth,
10389+ const char *errmsg, enum tls_fail_reason reason)
10390+{
10391+ struct tls_config *init_conf = &tls_ctx_global.init_conf;
10392+ if (init_conf->event_cb == NULL)
10393+ return;
10394+
10395+ struct wpabuf *certbuf = wpabuf_alloc_copy(crt->raw.p, crt->raw.len);
10396+ char subject[MBEDTLS_X509_MAX_DN_NAME_SIZE*2];
10397+ if (mbedtls_x509_dn_gets(subject, sizeof(subject), &crt->subject) < 0)
10398+ subject[0] = '\0';
10399+ union tls_event_data ev;
10400+ os_memset(&ev, 0, sizeof(ev));
10401+ ev.cert_fail.reason = reason;
10402+ ev.cert_fail.depth = depth;
10403+ ev.cert_fail.subject = subject;
10404+ ev.cert_fail.reason_txt = errmsg;
10405+ ev.cert_fail.cert = certbuf;
10406+
10407+ init_conf->event_cb(init_conf->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
10408+
10409+ wpabuf_free(certbuf);
10410+}
10411+
10412+
10413+__attribute_noinline__
10414+static void
10415+tls_mbedtls_verify_cert_event (struct tls_connection *conn,
10416+ mbedtls_x509_crt *crt, int depth)
10417+{
10418+ struct tls_config *init_conf = &tls_ctx_global.init_conf;
10419+ if (init_conf->event_cb == NULL)
10420+ return;
10421+
10422+ struct wpabuf *certbuf = NULL;
10423+ union tls_event_data ev;
10424+ os_memset(&ev, 0, sizeof(ev));
10425+
10426+ #ifdef MBEDTLS_SHA256_C
10427+ u8 hash[SHA256_DIGEST_LENGTH];
10428+ const u8 *addr[] = { (u8 *)crt->raw.p };
10429+ if (sha256_vector(1, addr, &crt->raw.len, hash) == 0) {
10430+ ev.peer_cert.hash = hash;
10431+ ev.peer_cert.hash_len = sizeof(hash);
10432+ }
10433+ #endif
10434+ ev.peer_cert.depth = depth;
10435+ char subject[MBEDTLS_X509_MAX_DN_NAME_SIZE*2];
10436+ if (depth == 0)
10437+ ev.peer_cert.subject = conn->peer_subject;
10438+ if (ev.peer_cert.subject == NULL) {
10439+ ev.peer_cert.subject = subject;
10440+ if (mbedtls_x509_dn_gets(subject, sizeof(subject), &crt->subject) < 0)
10441+ subject[0] = '\0';
10442+ }
10443+
10444+ char serial_num[128+1];
10445+ ev.peer_cert.serial_num =
10446+ tls_mbedtls_peer_serial_num(crt, serial_num, sizeof(serial_num));
10447+
10448+ const mbedtls_x509_sequence *cur;
10449+
10450+ cur = NULL;
10451+ if (mbedtls_x509_crt_has_ext_type(crt, MBEDTLS_X509_EXT_SUBJECT_ALT_NAME))
10452+ cur = &crt->subject_alt_names;
10453+ for (; cur != NULL; cur = cur->next) {
10454+ const unsigned char san_type = (unsigned char)cur->buf.tag
10455+ & MBEDTLS_ASN1_TAG_VALUE_MASK;
10456+ size_t prelen = 4;
10457+ const char *pre;
10458+ switch (san_type) {
10459+ case MBEDTLS_X509_SAN_RFC822_NAME: prelen = 6; pre = "EMAIL:";break;
10460+ case MBEDTLS_X509_SAN_DNS_NAME: pre = "DNS:"; break;
10461+ case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: pre = "URI:"; break;
10462+ default: continue;
10463+ }
10464+
10465+ char *pos = os_malloc(prelen + cur->buf.len + 1);
10466+ if (pos == NULL)
10467+ break;
10468+ ev.peer_cert.altsubject[ev.peer_cert.num_altsubject] = pos;
10469+ os_memcpy(pos, pre, prelen);
10470+ /* data should be properly backslash-escaped if needed,
10471+ * so code below does not re-escape, but does replace CTLs */
10472+ /*os_memcpy(pos+prelen, cur->buf.p, cur->buf.len);*/
10473+ /*pos[prelen+cur->buf.len] = '\0';*/
10474+ pos += prelen;
10475+ for (size_t i = 0; i < cur->buf.len; ++i) {
10476+ unsigned char c = cur->buf.p[i];
10477+ *pos++ = (c >= 32 && c != 127) ? c : '?';
10478+ }
10479+ *pos = '\0';
10480+
10481+ if (++ev.peer_cert.num_altsubject == TLS_MAX_ALT_SUBJECT)
10482+ break;
10483+ }
10484+
10485+ cur = NULL;
10486+ if (mbedtls_x509_crt_has_ext_type(crt, MBEDTLS_X509_EXT_CERTIFICATE_POLICIES))
10487+ cur = &crt->certificate_policies;
10488+ for (; cur != NULL; cur = cur->next) {
10489+ if (cur->buf.len != 11) /* len of OID_TOD_STRICT or OID_TOD_TOFU */
10490+ continue;
10491+ /* TOD-STRICT "1.3.6.1.4.1.40808.1.3.1" */
10492+ /* TOD-TOFU "1.3.6.1.4.1.40808.1.3.2" */
10493+ #define OID_TOD_STRICT "\x2b\x06\x01\x04\x01\x82\xbe\x68\x01\x03\x01"
10494+ #define OID_TOD_TOFU "\x2b\x06\x01\x04\x01\x82\xbe\x68\x01\x03\x02"
10495+ if (os_memcmp(cur->buf.p,
10496+ OID_TOD_STRICT, sizeof(OID_TOD_STRICT)-1) == 0) {
10497+ ev.peer_cert.tod = 1; /* TOD-STRICT */
10498+ break;
10499+ }
10500+ if (os_memcmp(cur->buf.p,
10501+ OID_TOD_TOFU, sizeof(OID_TOD_TOFU)-1) == 0) {
10502+ ev.peer_cert.tod = 2; /* TOD-TOFU */
10503+ break;
10504+ }
10505+ }
10506+
10507+ struct tls_conf *tls_conf = conn->tls_conf;
10508+ if (tls_conf->ca_cert_probe || (tls_conf->flags & TLS_CONN_EXT_CERT_CHECK)
10509+ || init_conf->cert_in_cb) {
10510+ certbuf = wpabuf_alloc_copy(crt->raw.p, crt->raw.len);
10511+ ev.peer_cert.cert = certbuf;
10512+ }
10513+
10514+ init_conf->event_cb(init_conf->cb_ctx, TLS_PEER_CERTIFICATE, &ev);
10515+
10516+ wpabuf_free(certbuf);
10517+ char **altsubject;
10518+ *(const char ***)&altsubject = ev.peer_cert.altsubject;
10519+ for (size_t i = 0; i < ev.peer_cert.num_altsubject; ++i)
10520+ os_free(altsubject[i]);
10521+}
10522+
10523+
10524+static int
10525+tls_mbedtls_verify_cb (void *arg, mbedtls_x509_crt *crt, int depth, uint32_t *flags)
10526+{
10527+ /* XXX: N.B. verify code not carefully tested besides hwsim tests
10528+ *
10529+ * RFE: mbedtls_x509_crt_verify_info() and enhance log trace messages
10530+ * RFE: review and add support for additional TLS_CONN_* flags
10531+ * not handling OCSP (not available in mbedtls)
10532+ * ... */
10533+
10534+ struct tls_connection *conn = (struct tls_connection *)arg;
10535+ struct tls_conf *tls_conf = conn->tls_conf;
10536+ uint32_t flags_in = *flags;
10537+
10538+ if (depth > 8) { /*(depth 8 picked as arbitrary limit)*/
10539+ emsg(MSG_WARNING, "client cert chain too long");
10540+ *flags |= MBEDTLS_X509_BADCERT_OTHER; /* cert chain too long */
10541+ tls_mbedtls_verify_fail_event(crt, depth,
10542+ "client cert chain too long",
10543+ TLS_FAIL_BAD_CERTIFICATE);
10544+ }
10545+ else if (tls_conf->verify_depth0_only) {
10546+ if (depth > 0)
10547+ *flags = 0;
10548+ else {
10549+ #ifdef MBEDTLS_SHA256_C
10550+ u8 hash[SHA256_DIGEST_LENGTH];
10551+ const u8 *addr[] = { (u8 *)crt->raw.p };
10552+ if (sha256_vector(1, addr, &crt->raw.len, hash) < 0
10553+ || os_memcmp(tls_conf->ca_cert_hash, hash, sizeof(hash)) != 0) {
10554+ *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
10555+ tls_mbedtls_verify_fail_event(crt, depth,
10556+ "cert hash mismatch",
10557+ TLS_FAIL_UNTRUSTED);
10558+ }
10559+ else /* hash matches; ignore other issues *except* if revoked)*/
10560+ *flags &= MBEDTLS_X509_BADCERT_REVOKED;
10561+ #endif
10562+ }
10563+ }
10564+ else if (depth == 0) {
10565+ if (!conn->peer_subject)
10566+ tls_mbedtls_set_peer_subject(conn, crt);
10567+ /*(use same labels to tls_mbedtls_verify_fail_event() as used in
10568+ * other TLS modules so that hwsim tests find exact string match)*/
10569+ if (!conn->peer_subject) { /* error copying subject string */
10570+ *flags |= MBEDTLS_X509_BADCERT_OTHER;
10571+ tls_mbedtls_verify_fail_event(crt, depth,
10572+ "internal error",
10573+ TLS_FAIL_UNSPECIFIED);
10574+ }
10575+ /*(use os_strstr() for subject match as is done in tls_mbedtls.c
10576+ * to follow the same behavior, even though a suffix match would
10577+ * make more sense. Also, note that strstr match does not
10578+ * normalize whitespace (between components) for comparison)*/
10579+ else if (tls_conf->subject_match
10580+ && os_strstr(conn->peer_subject,
10581+ tls_conf->subject_match) == NULL) {
10582+ wpa_printf(MSG_WARNING,
10583+ "MTLS: Subject '%s' did not match with '%s'",
10584+ conn->peer_subject, tls_conf->subject_match);
10585+ *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
10586+ tls_mbedtls_verify_fail_event(crt, depth,
10587+ "Subject mismatch",
10588+ TLS_FAIL_SUBJECT_MISMATCH);
10589+ }
10590+ if (tls_conf->altsubject_match
10591+ && !tls_mbedtls_match_altsubject(crt, tls_conf->altsubject_match)) {
10592+ wpa_printf(MSG_WARNING,
10593+ "MTLS: altSubjectName match '%s' not found",
10594+ tls_conf->altsubject_match);
10595+ *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
10596+ tls_mbedtls_verify_fail_event(crt, depth,
10597+ "AltSubject mismatch",
10598+ TLS_FAIL_ALTSUBJECT_MISMATCH);
10599+ }
10600+ if (tls_conf->suffix_match
10601+ && !tls_mbedtls_match_suffixes(crt, tls_conf->suffix_match, 0)) {
10602+ wpa_printf(MSG_WARNING,
10603+ "MTLS: Domain suffix match '%s' not found",
10604+ tls_conf->suffix_match);
10605+ *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
10606+ tls_mbedtls_verify_fail_event(crt, depth,
10607+ "Domain suffix mismatch",
10608+ TLS_FAIL_DOMAIN_SUFFIX_MISMATCH);
10609+ }
10610+ if (tls_conf->domain_match
10611+ && !tls_mbedtls_match_suffixes(crt, tls_conf->domain_match, 1)) {
10612+ wpa_printf(MSG_WARNING,
10613+ "MTLS: Domain match '%s' not found",
10614+ tls_conf->domain_match);
10615+ *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
10616+ tls_mbedtls_verify_fail_event(crt, depth,
10617+ "Domain mismatch",
10618+ TLS_FAIL_DOMAIN_MISMATCH);
10619+ }
10620+ if (tls_conf->check_cert_subject
10621+ && !tls_mbedtls_match_dn_field(crt, tls_conf->check_cert_subject)) {
10622+ *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
10623+ tls_mbedtls_verify_fail_event(crt, depth,
10624+ "Distinguished Name",
10625+ TLS_FAIL_DN_MISMATCH);
10626+ }
10627+ if (tls_conf->flags & TLS_CONN_SUITEB) {
10628+ /* check RSA modulus size (public key bitlen) */
10629+ const mbedtls_pk_type_t pk_alg = mbedtls_pk_get_type(&crt->pk);
10630+ if ((pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS)
10631+ && mbedtls_pk_get_bitlen(&crt->pk) < 3072) {
10632+ /* hwsim suite_b RSA tests expect 3072
10633+ * suite_b_192_rsa_ecdhe_radius_rsa2048_client
10634+ * suite_b_192_rsa_dhe_radius_rsa2048_client */
10635+ *flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
10636+ tls_mbedtls_verify_fail_event(crt, depth,
10637+ "Insufficient RSA modulus size",
10638+ TLS_FAIL_INSUFFICIENT_KEY_LEN);
10639+ }
10640+ }
10641+ if (tls_conf->check_crl && tls_conf->crl == NULL) {
10642+ /* see tests/hwsim test_ap_eap.py ap_wpa2_eap_tls_check_crl */
10643+ emsg(MSG_WARNING, "check_crl set but no CRL loaded; reject all?");
10644+ *flags |= MBEDTLS_X509_BADCERT_OTHER;
10645+ tls_mbedtls_verify_fail_event(crt, depth,
10646+ "check_crl set but no CRL loaded; "
10647+ "reject all?",
10648+ TLS_FAIL_BAD_CERTIFICATE);
10649+ }
10650+ }
10651+ else {
10652+ if (tls_conf->check_crl != 2) /* 2 == verify CRLs for all certs */
10653+ *flags &= ~MBEDTLS_X509_BADCERT_REVOKED;
10654+ }
10655+
10656+ if (!tls_conf->check_crl_strict) {
10657+ *flags &= ~MBEDTLS_X509_BADCRL_EXPIRED;
10658+ *flags &= ~MBEDTLS_X509_BADCRL_FUTURE;
10659+ }
10660+
10661+ if (tls_conf->flags & TLS_CONN_DISABLE_TIME_CHECKS) {
10662+ *flags &= ~MBEDTLS_X509_BADCERT_EXPIRED;
10663+ *flags &= ~MBEDTLS_X509_BADCERT_FUTURE;
10664+ }
10665+
10666+ tls_mbedtls_verify_cert_event(conn, crt, depth);
10667+
10668+ if (*flags) {
10669+ if (*flags & (MBEDTLS_X509_BADCERT_NOT_TRUSTED
10670+ |MBEDTLS_X509_BADCERT_CN_MISMATCH
10671+ |MBEDTLS_X509_BADCERT_REVOKED)) {
10672+ emsg(MSG_WARNING, "client cert not trusted");
10673+ }
10674+ /* report event if flags set but no additional flags set above */
10675+ /* (could translate flags to more detailed TLS_FAIL_* if needed) */
10676+ if (!(*flags & ~flags_in)) {
10677+ enum tls_fail_reason reason = TLS_FAIL_UNSPECIFIED;
10678+ const char *errmsg = "cert verify fail unspecified";
10679+ if (*flags & MBEDTLS_X509_BADCERT_NOT_TRUSTED) {
10680+ reason = TLS_FAIL_UNTRUSTED;
10681+ errmsg = "certificate not trusted";
10682+ }
10683+ if (*flags & MBEDTLS_X509_BADCERT_REVOKED) {
10684+ reason = TLS_FAIL_REVOKED;
10685+ errmsg = "certificate has been revoked";
10686+ }
10687+ if (*flags & MBEDTLS_X509_BADCERT_FUTURE) {
10688+ reason = TLS_FAIL_NOT_YET_VALID;
10689+ errmsg = "certificate not yet valid";
10690+ }
10691+ if (*flags & MBEDTLS_X509_BADCERT_EXPIRED) {
10692+ reason = TLS_FAIL_EXPIRED;
10693+ errmsg = "certificate has expired";
10694+ }
10695+ if (*flags & MBEDTLS_X509_BADCERT_BAD_MD) {
10696+ reason = TLS_FAIL_BAD_CERTIFICATE;
10697+ errmsg = "certificate uses insecure algorithm";
10698+ }
10699+ tls_mbedtls_verify_fail_event(crt, depth, errmsg, reason);
10700+ }
10701+ #if 0
10702+ /* ??? send (again) cert events for all certs in chain ???
10703+ * (should already have been called for greater depths) */
10704+ /* tls_openssl.c:tls_verify_cb() sends cert events for all certs
10705+ * in chain if certificate validation fails, but sends all events
10706+ * with depth set to 0 (might be a bug) */
10707+ if (depth > 0) {
10708+ int pdepth = depth + 1;
10709+ for (mbedtls_x509_crt *pcrt; (pcrt = crt->next); ++pdepth) {
10710+ tls_mbedtls_verify_cert_event(conn, pcrt, pdepth);
10711+ }
10712+ }
10713+ #endif
10714+ /*(do not preserve subject if verification failed but was optional)*/
10715+ if (depth == 0 && conn->peer_subject) {
10716+ os_free(conn->peer_subject);
10717+ conn->peer_subject = NULL;
10718+ }
10719+ }
10720+ else if (depth == 0) {
10721+ struct tls_config *init_conf = &tls_ctx_global.init_conf;
10722+ if (tls_conf->ca_cert_probe) {
10723+ /* reject server certificate on probe-only run */
10724+ *flags |= MBEDTLS_X509_BADCERT_OTHER;
10725+ tls_mbedtls_verify_fail_event(crt, depth,
10726+ "server chain probe",
10727+ TLS_FAIL_SERVER_CHAIN_PROBE);
10728+ }
10729+ else if (init_conf->event_cb) {
10730+ /* ??? send event as soon as depth == 0 is verified ???
10731+ * What about rest of chain?
10732+ * Follows tls_mbedtls.c behavior: */
10733+ init_conf->event_cb(init_conf->cb_ctx,
10734+ TLS_CERT_CHAIN_SUCCESS, NULL);
10735+ }
10736+ }
10737+
10738+ return 0;
10739+}
10740diff --git a/src/drivers/driver.h b/src/drivers/driver.h
developer05f3b2b2024-08-19 19:17:34 +080010741index 4331782d8..e1a447333 100644
developer66e89bc2024-04-23 14:50:01 +080010742--- a/src/drivers/driver.h
10743+++ b/src/drivers/driver.h
developer05f3b2b2024-08-19 19:17:34 +080010744@@ -979,6 +979,9 @@ struct wpa_driver_associate_params {
developer66e89bc2024-04-23 14:50:01 +080010745 * responsible for selecting with which BSS to associate. */
10746 const u8 *bssid;
10747
developer05f3b2b2024-08-19 19:17:34 +080010748+ unsigned char rates[WLAN_SUPP_RATES_MAX];
developer66e89bc2024-04-23 14:50:01 +080010749+ int mcast_rate;
10750+
10751 /**
10752 * bssid_hint - BSSID of a proposed AP
10753 *
developer05f3b2b2024-08-19 19:17:34 +080010754@@ -1886,6 +1889,7 @@ struct wpa_driver_mesh_join_params {
developer66e89bc2024-04-23 14:50:01 +080010755 #define WPA_DRIVER_MESH_FLAG_AMPE 0x00000008
10756 unsigned int flags;
10757 bool handle_dfs;
10758+ int mcast_rate;
10759 };
10760
10761 struct wpa_driver_set_key_params {
developer05f3b2b2024-08-19 19:17:34 +080010762@@ -2357,6 +2361,9 @@ struct wpa_driver_capa {
developer66e89bc2024-04-23 14:50:01 +080010763 /** Maximum number of iterations in a single scan plan */
10764 u32 max_sched_scan_plan_iterations;
10765
10766+ /** Maximum number of extra IE bytes for scans */
10767+ u16 max_scan_ie_len;
10768+
10769 /** Whether sched_scan (offloaded scanning) is supported */
10770 int sched_scan_supported;
10771
developer05f3b2b2024-08-19 19:17:34 +080010772@@ -3887,6 +3894,25 @@ struct wpa_driver_ops {
developer66e89bc2024-04-23 14:50:01 +080010773 int (*if_remove)(void *priv, enum wpa_driver_if_type type,
10774 const char *ifname);
10775
10776+ /**
10777+ * if_rename - Rename a virtual interface
10778+ * @priv: Private driver interface data
10779+ * @type: Interface type
10780+ * @ifname: Interface name of the virtual interface to be renamed
10781+ * (NULL when renaming the AP BSS interface)
10782+ * @new_name: New interface name of the virtual interface
10783+ * Returns: 0 on success, -1 on failure
10784+ */
10785+ int (*if_rename)(void *priv, enum wpa_driver_if_type type,
10786+ const char *ifname, const char *new_name);
10787+
10788+ /**
10789+ * set_first_bss - Make a virtual interface the first (primary) bss
10790+ * @priv: Private driver interface data
10791+ * Returns: 0 on success, -1 on failure
10792+ */
10793+ int (*set_first_bss)(void *priv);
10794+
10795 /**
10796 * set_sta_vlan - Bind a station into a specific interface (AP only)
10797 * @priv: Private driver interface data
developer05f3b2b2024-08-19 19:17:34 +080010798@@ -3989,7 +4015,7 @@ struct wpa_driver_ops {
10799 * Returns: 0 on success, -1 on failure
10800 */
10801 int (*set_wds_sta)(void *priv, const u8 *addr, int aid, int val,
10802- const char *bridge_ifname, char *ifname_wds);
10803+ const char *bridge_ifname, const char *ifname_wds);
10804
10805 /**
10806 * send_action - Transmit an Action frame
10807@@ -4291,7 +4317,7 @@ struct wpa_driver_ops {
developer66e89bc2024-04-23 14:50:01 +080010808 * Returns: 0 on success, negative (<0) on failure
10809 */
10810 int (*br_set_net_param)(void *priv, enum drv_br_net_param param,
10811- unsigned int val);
10812+ const char *ifname, unsigned int val);
10813
10814 /**
10815 * get_wowlan - Get wake-on-wireless status
developer05f3b2b2024-08-19 19:17:34 +080010816@@ -6588,6 +6614,7 @@ union wpa_event_data {
developer66e89bc2024-04-23 14:50:01 +080010817
10818 /**
10819 * struct ch_switch
10820+ * @count: Count until channel switch activates
10821 * @freq: Frequency of new channel in MHz
10822 * @ht_enabled: Whether this is an HT channel
10823 * @ch_offset: Secondary channel offset
developer05f3b2b2024-08-19 19:17:34 +080010824@@ -6598,6 +6625,7 @@ union wpa_event_data {
developer66e89bc2024-04-23 14:50:01 +080010825 * @punct_bitmap: Puncturing bitmap
10826 */
10827 struct ch_switch {
10828+ int count;
10829 int freq;
10830 int ht_enabled;
10831 int ch_offset;
developer05f3b2b2024-08-19 19:17:34 +080010832@@ -6846,8 +6874,8 @@ union wpa_event_data {
developer66e89bc2024-04-23 14:50:01 +080010833 * Driver wrapper code should call this function whenever an event is received
10834 * from the driver.
10835 */
10836-void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
10837- union wpa_event_data *data);
10838+extern void (*wpa_supplicant_event)(void *ctx, enum wpa_event_type event,
10839+ union wpa_event_data *data);
10840
10841 /**
10842 * wpa_supplicant_event_global - Report a driver event for wpa_supplicant
developer05f3b2b2024-08-19 19:17:34 +080010843@@ -6859,7 +6887,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
developer66e89bc2024-04-23 14:50:01 +080010844 * Same as wpa_supplicant_event(), but we search for the interface in
10845 * wpa_global.
10846 */
10847-void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
10848+extern void (*wpa_supplicant_event_global)(void *ctx, enum wpa_event_type event,
10849 union wpa_event_data *data);
10850
10851 /*
10852diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
developer05f3b2b2024-08-19 19:17:34 +080010853index 39f58ff83..a70eaae38 100644
developer66e89bc2024-04-23 14:50:01 +080010854--- a/src/drivers/driver_nl80211.c
10855+++ b/src/drivers/driver_nl80211.c
developer05f3b2b2024-08-19 19:17:34 +080010856@@ -75,6 +75,16 @@ enum nlmsgerr_attrs {
developer66e89bc2024-04-23 14:50:01 +080010857
10858 #endif /* ANDROID */
10859
10860+static void handle_nl_debug_hook(struct nl_msg *msg, int tx)
10861+{
10862+ const struct nlmsghdr *nlh;
10863+
10864+ if (!wpa_netlink_hook)
10865+ return;
10866+
10867+ nlh = nlmsg_hdr(msg);
10868+ wpa_netlink_hook(tx, nlh, nlh->nlmsg_len);
10869+}
10870
10871 static struct nl_sock * nl_create_handle(struct nl_cb *cb, const char *dbg)
10872 {
developer05f3b2b2024-08-19 19:17:34 +080010873@@ -429,6 +439,11 @@ static int no_seq_check(struct nl_msg *msg, void *arg)
developer66e89bc2024-04-23 14:50:01 +080010874 return NL_OK;
10875 }
10876
10877+static int debug_handler(struct nl_msg *msg, void *arg)
10878+{
10879+ handle_nl_debug_hook(msg, 0);
10880+ return NL_OK;
10881+}
10882
10883 static void nl80211_nlmsg_clear(struct nl_msg *msg)
10884 {
developer05f3b2b2024-08-19 19:17:34 +080010885@@ -502,6 +517,8 @@ int send_and_recv(struct nl80211_global *global,
developer66e89bc2024-04-23 14:50:01 +080010886 if (!msg)
10887 return -ENOMEM;
10888
10889+ handle_nl_debug_hook(msg, 1);
developer05f3b2b2024-08-19 19:17:34 +080010890+
developer66e89bc2024-04-23 14:50:01 +080010891 err.err = -ENOMEM;
10892
10893 s_nl_cb = nl_socket_get_cb(nl_handle);
developer05f3b2b2024-08-19 19:17:34 +080010894@@ -536,6 +553,7 @@ int send_and_recv(struct nl80211_global *global,
developer66e89bc2024-04-23 14:50:01 +080010895 err.orig_msg = msg;
10896 err.err_info = err_info;
10897
10898+ nl_cb_set(cb, NL_CB_MSG_IN, NL_CB_CUSTOM, debug_handler, NULL);
10899 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
10900 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err.err);
10901 if (ack_handler_custom) {
developer05f3b2b2024-08-19 19:17:34 +080010902@@ -939,6 +957,7 @@ nl80211_get_wiphy_data_ap(struct i802_bss *bss)
developer66e89bc2024-04-23 14:50:01 +080010903 os_free(w);
10904 return NULL;
10905 }
10906+ nl_cb_set(w->nl_cb, NL_CB_MSG_IN, NL_CB_CUSTOM, debug_handler, NULL);
10907 nl_cb_set(w->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
10908 no_seq_check, NULL);
10909 nl_cb_set(w->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
developer05f3b2b2024-08-19 19:17:34 +080010910@@ -1353,7 +1372,7 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
developer66e89bc2024-04-23 14:50:01 +080010911 }
10912 wpa_printf(MSG_DEBUG, "nl80211: Interface down (%s/%s)",
10913 namebuf, ifname);
10914- if (os_strcmp(drv->first_bss->ifname, ifname) != 0) {
10915+ if (drv->first_bss->ifindex != ifi->ifi_index) {
10916 wpa_printf(MSG_DEBUG,
10917 "nl80211: Not the main interface (%s) - do not indicate interface down",
10918 drv->first_bss->ifname);
developer05f3b2b2024-08-19 19:17:34 +080010919@@ -1389,7 +1408,7 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
developer66e89bc2024-04-23 14:50:01 +080010920 }
10921 wpa_printf(MSG_DEBUG, "nl80211: Interface up (%s/%s)",
10922 namebuf, ifname);
10923- if (os_strcmp(drv->first_bss->ifname, ifname) != 0) {
10924+ if (drv->first_bss->ifindex != ifi->ifi_index) {
10925 wpa_printf(MSG_DEBUG,
10926 "nl80211: Not the main interface (%s) - do not indicate interface up",
10927 drv->first_bss->ifname);
developer05f3b2b2024-08-19 19:17:34 +080010928@@ -2035,6 +2054,7 @@ static int wpa_driver_nl80211_init_nl_global(struct nl80211_global *global)
developer66e89bc2024-04-23 14:50:01 +080010929 genl_family_put(family);
10930 nl_cache_free(cache);
10931
10932+ nl_cb_set(global->nl_cb, NL_CB_MSG_IN, NL_CB_CUSTOM, debug_handler, NULL);
10933 nl_cb_set(global->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
10934 no_seq_check, NULL);
10935 nl_cb_set(global->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
developer05f3b2b2024-08-19 19:17:34 +080010936@@ -2205,6 +2225,7 @@ static int nl80211_init_bss(struct i802_bss *bss)
developer66e89bc2024-04-23 14:50:01 +080010937 if (!bss->nl_cb)
10938 return -1;
10939
10940+ nl_cb_set(bss->nl_cb, NL_CB_MSG_IN, NL_CB_CUSTOM, debug_handler, NULL);
10941 nl_cb_set(bss->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
10942 no_seq_check, NULL);
10943 nl_cb_set(bss->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
developer05f3b2b2024-08-19 19:17:34 +080010944@@ -3083,7 +3104,7 @@ static int wpa_driver_nl80211_del_beacon(struct i802_bss *bss,
10945 struct wpa_driver_nl80211_data *drv = bss->drv;
10946 struct i802_link *link = nl80211_get_link(bss, link_id);
10947
10948- if (!link->beacon_set)
10949+ if (!link || !link->beacon_set)
10950 return 0;
10951
10952 wpa_printf(MSG_DEBUG, "nl80211: Remove beacon (ifindex=%d)",
10953@@ -5494,7 +5515,7 @@ static int nl80211_set_channel(struct i802_bss *bss,
developer66e89bc2024-04-23 14:50:01 +080010954 freq->he_enabled, freq->eht_enabled, freq->bandwidth,
10955 freq->center_freq1, freq->center_freq2);
10956
10957- msg = nl80211_drv_msg(drv, 0, set_chan ? NL80211_CMD_SET_CHANNEL :
10958+ msg = nl80211_bss_msg(bss, 0, set_chan ? NL80211_CMD_SET_CHANNEL :
10959 NL80211_CMD_SET_WIPHY);
10960 if (!msg || nl80211_put_freq_params(msg, freq) < 0) {
10961 nlmsg_free(msg);
developer05f3b2b2024-08-19 19:17:34 +080010962@@ -6183,8 +6204,7 @@ static void nl80211_teardown_ap(struct i802_bss *bss)
10963 nl80211_mgmt_unsubscribe(bss, "AP teardown");
developer66e89bc2024-04-23 14:50:01 +080010964
developer66e89bc2024-04-23 14:50:01 +080010965 nl80211_put_wiphy_data_ap(bss);
developer05f3b2b2024-08-19 19:17:34 +080010966- if (bss->flink)
10967- bss->flink->beacon_set = 0;
developer66e89bc2024-04-23 14:50:01 +080010968+ wpa_driver_nl80211_del_beacon_all(bss);
10969 }
10970
10971
developer05f3b2b2024-08-19 19:17:34 +080010972@@ -8414,24 +8434,14 @@ static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx,
10973
10974
10975 static int i802_set_wds_sta(void *priv, const u8 *addr, int aid, int val,
10976- const char *bridge_ifname, char *ifname_wds)
10977+ const char *bridge_ifname, const char *ifname_wds)
10978 {
10979 struct i802_bss *bss = priv;
10980 struct wpa_driver_nl80211_data *drv = bss->drv;
10981- char name[IFNAMSIZ + 1];
10982+ const char *name = ifname_wds; // Kept to reduce changes to the minimum
10983 union wpa_event_data event;
10984 int ret;
10985
10986- ret = os_snprintf(name, sizeof(name), "%s.sta%d", bss->ifname, aid);
10987- if (ret >= (int) sizeof(name))
10988- wpa_printf(MSG_WARNING,
10989- "nl80211: WDS interface name was truncated");
10990- else if (ret < 0)
10991- return ret;
10992-
10993- if (ifname_wds)
10994- os_strlcpy(ifname_wds, name, IFNAMSIZ + 1);
10995-
10996 wpa_printf(MSG_DEBUG, "nl80211: Set WDS STA addr=" MACSTR
10997 " aid=%d val=%d name=%s", MAC2STR(addr), aid, val, name);
10998 if (val) {
10999@@ -8574,6 +8584,7 @@ static void *i802_init(struct hostapd_data *hapd,
developer66e89bc2024-04-23 14:50:01 +080011000 char master_ifname[IFNAMSIZ];
11001 int ifindex, br_ifindex = 0;
11002 int br_added = 0;
11003+ int err;
11004
11005 bss = wpa_driver_nl80211_drv_init(hapd, params->ifname,
11006 params->global_priv, 1,
developer05f3b2b2024-08-19 19:17:34 +080011007@@ -8633,21 +8644,17 @@ static void *i802_init(struct hostapd_data *hapd,
developer66e89bc2024-04-23 14:50:01 +080011008 (params->num_bridge == 0 || !params->bridge[0]))
11009 add_ifidx(drv, br_ifindex, drv->ifindex);
11010
developer66e89bc2024-04-23 14:50:01 +080011011- if (bss->added_if_into_bridge || bss->already_in_bridge) {
11012- int err;
11013-
11014- drv->rtnl_sk = nl_socket_alloc();
11015- if (drv->rtnl_sk == NULL) {
11016- wpa_printf(MSG_ERROR, "nl80211: Failed to allocate nl_sock");
11017- goto failed;
11018- }
11019+ drv->rtnl_sk = nl_socket_alloc();
11020+ if (drv->rtnl_sk == NULL) {
11021+ wpa_printf(MSG_ERROR, "nl80211: Failed to allocate nl_sock");
11022+ goto failed;
11023+ }
11024
11025- err = nl_connect(drv->rtnl_sk, NETLINK_ROUTE);
11026- if (err) {
11027- wpa_printf(MSG_ERROR, "nl80211: Failed to connect nl_sock to NETLINK_ROUTE: %s",
11028- nl_geterror(err));
11029- goto failed;
11030- }
11031+ err = nl_connect(drv->rtnl_sk, NETLINK_ROUTE);
11032+ if (err) {
11033+ wpa_printf(MSG_ERROR, "nl80211: Failed to connect nl_sock to NETLINK_ROUTE: %s",
11034+ nl_geterror(err));
11035+ goto failed;
11036 }
developer66e89bc2024-04-23 14:50:01 +080011037
11038 if (drv->capa.flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX) {
developer05f3b2b2024-08-19 19:17:34 +080011039@@ -8998,8 +9005,6 @@ static int wpa_driver_nl80211_if_remove(struct i802_bss *bss,
11040 wpa_printf(MSG_DEBUG, "nl80211: First BSS - reassign context");
11041 nl80211_teardown_ap(bss);
11042 nl80211_remove_links(bss);
11043- if (!bss->added_if && !drv->first_bss->next)
11044- wpa_driver_nl80211_del_beacon_all(bss);
11045 nl80211_destroy_bss(bss);
11046 if (!bss->added_if)
11047 i802_set_iface_flags(bss, 0);
11048@@ -9016,6 +9021,50 @@ static int wpa_driver_nl80211_if_remove(struct i802_bss *bss,
developer66e89bc2024-04-23 14:50:01 +080011049 return 0;
11050 }
11051
11052+static int wpa_driver_nl80211_if_rename(struct i802_bss *bss,
11053+ enum wpa_driver_if_type type,
11054+ const char *ifname, const char *new_name)
11055+{
11056+ struct wpa_driver_nl80211_data *drv = bss->drv;
11057+ struct ifinfomsg ifi = {
11058+ .ifi_family = AF_UNSPEC,
11059+ .ifi_index = bss->ifindex,
11060+ };
11061+ struct nl_msg *msg;
11062+ int res = -ENOMEM;
11063+
11064+ if (ifname)
11065+ ifi.ifi_index = if_nametoindex(ifname);
11066+
11067+ msg = nlmsg_alloc_simple(RTM_SETLINK, 0);
11068+ if (!msg)
11069+ return res;
11070+
11071+ if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0)
11072+ goto out;
11073+
11074+ if (nla_put_string(msg, IFLA_IFNAME, new_name))
11075+ goto out;
11076+
11077+ res = nl_send_auto_complete(drv->rtnl_sk, msg);
11078+ if (res < 0)
11079+ goto out;
11080+
11081+ res = nl_wait_for_ack(drv->rtnl_sk);
11082+ if (res) {
11083+ wpa_printf(MSG_INFO,
11084+ "nl80211: Renaming device %s to %s failed: %s",
11085+ ifname ? ifname : bss->ifname, new_name, nl_geterror(res));
11086+ goto out;
11087+ }
11088+
11089+ if (type == WPA_IF_AP_BSS && !ifname)
11090+ os_strlcpy(bss->ifname, new_name, sizeof(bss->ifname));
11091+
11092+out:
11093+ nlmsg_free(msg);
11094+ return res;
11095+}
11096
11097 static int cookie_handler(struct nl_msg *msg, void *arg)
11098 {
developer05f3b2b2024-08-19 19:17:34 +080011099@@ -10807,6 +10856,37 @@ static bool nl80211_is_drv_shared(void *priv, void *bss_ctx)
developer66e89bc2024-04-23 14:50:01 +080011100 #endif /* CONFIG_IEEE80211BE */
11101
11102
11103+static int driver_nl80211_if_rename(void *priv, enum wpa_driver_if_type type,
11104+ const char *ifname, const char *new_name)
11105+{
11106+ struct i802_bss *bss = priv;
11107+ return wpa_driver_nl80211_if_rename(bss, type, ifname, new_name);
11108+}
11109+
11110+
11111+static int driver_nl80211_set_first_bss(void *priv)
11112+{
11113+ struct i802_bss *bss = priv, *tbss;
11114+ struct wpa_driver_nl80211_data *drv = bss->drv;
11115+
11116+ if (drv->first_bss == bss)
11117+ return 0;
11118+
11119+ for (tbss = drv->first_bss; tbss; tbss = tbss->next) {
11120+ if (tbss->next != bss)
11121+ continue;
11122+
11123+ tbss->next = bss->next;
11124+ bss->next = drv->first_bss;
11125+ drv->first_bss = bss;
11126+ drv->ctx = bss->ctx;
11127+ return 0;
11128+ }
11129+
11130+ return -1;
11131+}
11132+
11133+
11134 static int driver_nl80211_send_mlme(void *priv, const u8 *data,
11135 size_t data_len, int noack,
11136 unsigned int freq,
developer05f3b2b2024-08-19 19:17:34 +080011137@@ -11309,6 +11389,10 @@ static int nl80211_switch_channel(void *priv, struct csa_settings *settings)
developer66e89bc2024-04-23 14:50:01 +080011138 if (ret)
11139 goto error;
11140
11141+ if (drv->nlmode == NL80211_IFTYPE_MESH_POINT) {
11142+ nla_put_flag(msg, NL80211_ATTR_HANDLE_DFS);
11143+ }
11144+
11145 /* beacon_csa params */
11146 beacon_csa = nla_nest_start(msg, NL80211_ATTR_CSA_IES);
11147 if (!beacon_csa)
developer05f3b2b2024-08-19 19:17:34 +080011148@@ -11983,6 +12067,18 @@ static int nl80211_put_mesh_id(struct nl_msg *msg, const u8 *mesh_id,
developer66e89bc2024-04-23 14:50:01 +080011149 }
11150
11151
11152+static int nl80211_put_mcast_rate(struct nl_msg *msg, int mcast_rate)
11153+{
11154+ if (mcast_rate > 0) {
11155+ wpa_printf(MSG_DEBUG, " * mcast_rate=%.1f",
11156+ (double)mcast_rate / 10);
11157+ return nla_put_u32(msg, NL80211_ATTR_MCAST_RATE, mcast_rate);
11158+ }
11159+
11160+ return 0;
11161+}
11162+
11163+
11164 static int nl80211_put_mesh_config(struct nl_msg *msg,
11165 struct wpa_driver_mesh_bss_params *params)
11166 {
developer05f3b2b2024-08-19 19:17:34 +080011167@@ -12044,6 +12140,7 @@ static int nl80211_join_mesh(struct i802_bss *bss,
developer66e89bc2024-04-23 14:50:01 +080011168 nl80211_put_basic_rates(msg, params->basic_rates) ||
11169 nl80211_put_mesh_id(msg, params->meshid, params->meshid_len) ||
11170 nl80211_put_beacon_int(msg, params->beacon_int) ||
11171+ nl80211_put_mcast_rate(msg, params->mcast_rate) ||
11172 nl80211_put_dtim_period(msg, params->dtim_period))
11173 goto fail;
11174
developer05f3b2b2024-08-19 19:17:34 +080011175@@ -12397,7 +12494,7 @@ static const char * drv_br_net_param_str(enum drv_br_net_param param)
developer66e89bc2024-04-23 14:50:01 +080011176
developer66e89bc2024-04-23 14:50:01 +080011177
11178 static int wpa_driver_br_set_net_param(void *priv, enum drv_br_net_param param,
11179- unsigned int val)
11180+ const char *ifname, unsigned int val)
11181 {
11182 struct i802_bss *bss = priv;
11183 char path[128];
developer05f3b2b2024-08-19 19:17:34 +080011184@@ -12423,8 +12520,11 @@ static int wpa_driver_br_set_net_param(void *priv, enum drv_br_net_param param,
developer66e89bc2024-04-23 14:50:01 +080011185 return -EINVAL;
11186 }
11187
11188+ if (!ifname)
11189+ ifname = bss->brname;
11190+
11191 os_snprintf(path, sizeof(path), "/proc/sys/net/ipv%d/conf/%s/%s",
11192- ip_version, bss->brname, param_txt);
11193+ ip_version, ifname, param_txt);
11194
11195 set_val:
11196 if (linux_write_system_file(path, val))
developer05f3b2b2024-08-19 19:17:34 +080011197@@ -14027,6 +14127,8 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
developer66e89bc2024-04-23 14:50:01 +080011198 .set_acl = wpa_driver_nl80211_set_acl,
11199 .if_add = wpa_driver_nl80211_if_add,
11200 .if_remove = driver_nl80211_if_remove,
11201+ .if_rename = driver_nl80211_if_rename,
11202+ .set_first_bss = driver_nl80211_set_first_bss,
11203 .send_mlme = driver_nl80211_send_mlme,
11204 .get_hw_feature_data = nl80211_get_hw_feature_data,
11205 .sta_add = wpa_driver_nl80211_sta_add,
11206diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
developer05f3b2b2024-08-19 19:17:34 +080011207index 26c1f4140..d5ba66b10 100644
developer66e89bc2024-04-23 14:50:01 +080011208--- a/src/drivers/driver_nl80211_capa.c
11209+++ b/src/drivers/driver_nl80211_capa.c
11210@@ -976,6 +976,10 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
11211 nla_get_u32(tb[NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS]);
11212 }
11213
11214+ if (tb[NL80211_ATTR_MAX_SCAN_IE_LEN])
11215+ capa->max_scan_ie_len =
11216+ nla_get_u16(tb[NL80211_ATTR_MAX_SCAN_IE_LEN]);
11217+
11218 if (tb[NL80211_ATTR_MAX_MATCH_SETS])
11219 capa->max_match_sets =
11220 nla_get_u8(tb[NL80211_ATTR_MAX_MATCH_SETS]);
11221diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
developer05f3b2b2024-08-19 19:17:34 +080011222index aee815e97..768c72905 100644
developer66e89bc2024-04-23 14:50:01 +080011223--- a/src/drivers/driver_nl80211_event.c
11224+++ b/src/drivers/driver_nl80211_event.c
11225@@ -1196,6 +1196,7 @@ static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
11226 struct nlattr *bw, struct nlattr *cf1,
11227 struct nlattr *cf2,
11228 struct nlattr *punct_bitmap,
11229+ struct nlattr *count,
11230 int finished)
11231 {
11232 struct i802_bss *bss;
11233@@ -1259,6 +1260,8 @@ static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
11234 data.ch_switch.cf1 = nla_get_u32(cf1);
11235 if (cf2)
11236 data.ch_switch.cf2 = nla_get_u32(cf2);
11237+ if (count)
11238+ data.ch_switch.count = nla_get_u32(count);
11239
11240 if (link)
11241 data.ch_switch.link_id = nla_get_u8(link);
developer05f3b2b2024-08-19 19:17:34 +080011242@@ -3999,6 +4002,7 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
developer66e89bc2024-04-23 14:50:01 +080011243 tb[NL80211_ATTR_CENTER_FREQ1],
11244 tb[NL80211_ATTR_CENTER_FREQ2],
11245 tb[NL80211_ATTR_PUNCT_BITMAP],
11246+ tb[NL80211_ATTR_CH_SWITCH_COUNT],
11247 0);
11248 break;
11249 case NL80211_CMD_CH_SWITCH_NOTIFY:
developer05f3b2b2024-08-19 19:17:34 +080011250@@ -4011,6 +4015,7 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
developer66e89bc2024-04-23 14:50:01 +080011251 tb[NL80211_ATTR_CENTER_FREQ1],
11252 tb[NL80211_ATTR_CENTER_FREQ2],
11253 tb[NL80211_ATTR_PUNCT_BITMAP],
11254+ NULL,
11255 1);
11256 break;
11257 case NL80211_CMD_DISCONNECT:
11258diff --git a/src/drivers/driver_nl80211_scan.c b/src/drivers/driver_nl80211_scan.c
developer05f3b2b2024-08-19 19:17:34 +080011259index b055e684a..a8ea8f2cf 100644
developer66e89bc2024-04-23 14:50:01 +080011260--- a/src/drivers/driver_nl80211_scan.c
11261+++ b/src/drivers/driver_nl80211_scan.c
11262@@ -221,7 +221,7 @@ nl80211_scan_common(struct i802_bss *bss, u8 cmd,
11263 wpa_printf(MSG_DEBUG, "nl80211: Passive scan requested");
11264 }
11265
11266- if (params->extra_ies) {
11267+ if (params->extra_ies && drv->capa.max_scan_ie_len >= params->extra_ies_len) {
11268 wpa_hexdump(MSG_MSGDUMP, "nl80211: Scan extra IEs",
11269 params->extra_ies, params->extra_ies_len);
11270 if (nla_put(msg, NL80211_ATTR_IE, params->extra_ies_len,
11271diff --git a/src/drivers/drivers.c b/src/drivers/drivers.c
11272index e95df6ddb..9071da3cf 100644
11273--- a/src/drivers/drivers.c
11274+++ b/src/drivers/drivers.c
11275@@ -10,6 +10,10 @@
11276 #include "utils/common.h"
11277 #include "driver.h"
11278
11279+void (*wpa_supplicant_event)(void *ctx, enum wpa_event_type event,
11280+ union wpa_event_data *data);
11281+void (*wpa_supplicant_event_global)(void *ctx, enum wpa_event_type event,
11282+ union wpa_event_data *data);
11283
11284 const struct wpa_driver_ops *const wpa_drivers[] =
11285 {
11286diff --git a/src/drivers/drivers.mak b/src/drivers/drivers.mak
11287index a03d4a034..8da44d9f5 100644
11288--- a/src/drivers/drivers.mak
11289+++ b/src/drivers/drivers.mak
11290@@ -54,7 +54,6 @@ NEED_SME=y
11291 NEED_AP_MLME=y
11292 NEED_NETLINK=y
11293 NEED_LINUX_IOCTL=y
11294-NEED_RFKILL=y
11295 NEED_RADIOTAP=y
11296 NEED_LIBNL=y
11297 endif
11298@@ -111,7 +110,6 @@ DRV_WPA_CFLAGS += -DCONFIG_DRIVER_WEXT
11299 CONFIG_WIRELESS_EXTENSION=y
11300 NEED_NETLINK=y
11301 NEED_LINUX_IOCTL=y
11302-NEED_RFKILL=y
11303 endif
11304
11305 ifdef CONFIG_DRIVER_NDIS
11306@@ -137,7 +135,6 @@ endif
11307 ifdef CONFIG_WIRELESS_EXTENSION
11308 DRV_WPA_CFLAGS += -DCONFIG_WIRELESS_EXTENSION
11309 DRV_WPA_OBJS += ../src/drivers/driver_wext.o
11310-NEED_RFKILL=y
11311 endif
11312
11313 ifdef NEED_NETLINK
11314@@ -146,6 +143,7 @@ endif
11315
11316 ifdef NEED_RFKILL
11317 DRV_OBJS += ../src/drivers/rfkill.o
11318+DRV_WPA_CFLAGS += -DCONFIG_RFKILL
11319 endif
11320
11321 ifdef NEED_RADIOTAP
11322diff --git a/src/drivers/rfkill.h b/src/drivers/rfkill.h
11323index 0412ac330..e27565375 100644
11324--- a/src/drivers/rfkill.h
11325+++ b/src/drivers/rfkill.h
11326@@ -18,8 +18,24 @@ struct rfkill_config {
11327 void (*unblocked_cb)(void *ctx);
11328 };
11329
11330+#ifdef CONFIG_RFKILL
11331 struct rfkill_data * rfkill_init(struct rfkill_config *cfg);
11332 void rfkill_deinit(struct rfkill_data *rfkill);
11333 int rfkill_is_blocked(struct rfkill_data *rfkill);
11334+#else
11335+static inline struct rfkill_data * rfkill_init(struct rfkill_config *cfg)
11336+{
11337+ return (void *) 1;
11338+}
11339+
11340+static inline void rfkill_deinit(struct rfkill_data *rfkill)
11341+{
11342+}
11343+
11344+static inline int rfkill_is_blocked(struct rfkill_data *rfkill)
11345+{
11346+ return 0;
11347+}
11348+#endif
11349
11350 #endif /* RFKILL_H */
11351diff --git a/src/radius/radius_client.c b/src/radius/radius_client.c
11352index 2a7f36170..8e8903051 100644
11353--- a/src/radius/radius_client.c
11354+++ b/src/radius/radius_client.c
11355@@ -165,6 +165,8 @@ struct radius_client_data {
11356 */
11357 void *ctx;
11358
11359+ struct hostapd_ip_addr local_ip;
11360+
11361 /**
11362 * conf - RADIUS client configuration (list of RADIUS servers to use)
11363 */
11364@@ -818,6 +820,30 @@ static void radius_close_acct_socket(struct radius_client_data *radius)
11365 }
11366
11367
11368+/**
11369+ * radius_client_send - Get local address for the RADIUS auth socket
11370+ * @radius: RADIUS client context from radius_client_init()
11371+ * @addr: pointer to store the address
11372+ *
11373+ * This function returns the local address for the connection to the RADIUS
11374+ * auth server. It also opens the socket if it's not available yet.
11375+ */
11376+int radius_client_get_local_addr(struct radius_client_data *radius,
11377+ struct hostapd_ip_addr *addr)
11378+{
11379+ struct hostapd_radius_servers *conf = radius->conf;
11380+
11381+ if (conf->auth_server && radius->auth_sock < 0)
11382+ radius_client_init_auth(radius);
11383+
11384+ if (radius->auth_sock < 0)
11385+ return -1;
11386+
11387+ memcpy(addr, &radius->local_ip, sizeof(*addr));
11388+
11389+ return 0;
11390+}
11391+
11392 /**
11393 * radius_client_send - Send a RADIUS request
11394 * @radius: RADIUS client context from radius_client_init()
11395@@ -1711,6 +1737,10 @@ radius_change_server(struct radius_client_data *radius,
11396 wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u",
11397 inet_ntoa(claddr.sin_addr),
11398 ntohs(claddr.sin_port));
11399+ if (auth) {
11400+ radius->local_ip.af = AF_INET;
11401+ radius->local_ip.u.v4 = claddr.sin_addr;
11402+ }
11403 }
11404 break;
11405 #ifdef CONFIG_IPV6
11406@@ -1722,6 +1752,10 @@ radius_change_server(struct radius_client_data *radius,
11407 inet_ntop(AF_INET6, &claddr6.sin6_addr,
11408 abuf, sizeof(abuf)),
11409 ntohs(claddr6.sin6_port));
11410+ if (auth) {
11411+ radius->local_ip.af = AF_INET6;
11412+ radius->local_ip.u.v6 = claddr6.sin6_addr;
11413+ }
11414 }
11415 break;
11416 }
11417diff --git a/src/radius/radius_client.h b/src/radius/radius_client.h
11418index db40637ea..9a89b0382 100644
11419--- a/src/radius/radius_client.h
11420+++ b/src/radius/radius_client.h
11421@@ -274,6 +274,8 @@ int radius_client_register(struct radius_client_data *radius,
11422 void radius_client_set_interim_error_cb(struct radius_client_data *radius,
11423 void (*cb)(const u8 *addr, void *ctx),
11424 void *ctx);
11425+int radius_client_get_local_addr(struct radius_client_data *radius,
11426+ struct hostapd_ip_addr * addr);
11427 int radius_client_send(struct radius_client_data *radius,
11428 struct radius_msg *msg,
11429 RadiusType msg_type, const u8 *addr);
11430diff --git a/src/radius/radius_das.c b/src/radius/radius_das.c
developer05f3b2b2024-08-19 19:17:34 +080011431index 8d7c9b4c4..01913b08f 100644
developer66e89bc2024-04-23 14:50:01 +080011432--- a/src/radius/radius_das.c
11433+++ b/src/radius/radius_das.c
11434@@ -12,13 +12,26 @@
11435 #include "utils/common.h"
11436 #include "utils/eloop.h"
11437 #include "utils/ip_addr.h"
11438+#include "utils/list.h"
11439 #include "radius.h"
11440 #include "radius_das.h"
11441
11442
11443-struct radius_das_data {
11444+static struct dl_list das_ports = DL_LIST_HEAD_INIT(das_ports);
11445+
11446+struct radius_das_port {
11447+ struct dl_list list;
11448+ struct dl_list das_data;
11449+
11450+ int port;
11451 int sock;
11452+};
11453+
11454+struct radius_das_data {
11455+ struct dl_list list;
11456+ struct radius_das_port *port;
11457 u8 *shared_secret;
11458+ u8 *nas_identifier;
11459 size_t shared_secret_len;
11460 struct hostapd_ip_addr client_addr;
11461 unsigned int time_window;
developer05f3b2b2024-08-19 19:17:34 +080011462@@ -388,56 +401,17 @@ fail:
developer66e89bc2024-04-23 14:50:01 +080011463 }
11464
11465
11466-static void radius_das_receive(int sock, void *eloop_ctx, void *sock_ctx)
11467+static void
11468+radius_das_receive_msg(struct radius_das_data *das, struct radius_msg *msg,
11469+ struct sockaddr *from, socklen_t fromlen,
11470+ char *abuf, int from_port)
11471 {
11472- struct radius_das_data *das = eloop_ctx;
11473- u8 buf[1500];
11474- union {
11475- struct sockaddr_storage ss;
11476- struct sockaddr_in sin;
11477-#ifdef CONFIG_IPV6
11478- struct sockaddr_in6 sin6;
11479-#endif /* CONFIG_IPV6 */
11480- } from;
11481- char abuf[50];
11482- int from_port = 0;
11483- socklen_t fromlen;
11484- int len;
11485- struct radius_msg *msg, *reply = NULL;
11486+ struct radius_msg *reply = NULL;
11487 struct radius_hdr *hdr;
11488 struct wpabuf *rbuf;
11489+ struct os_time now;
11490 u32 val;
11491 int res;
11492- struct os_time now;
11493-
11494- fromlen = sizeof(from);
11495- len = recvfrom(sock, buf, sizeof(buf), 0,
11496- (struct sockaddr *) &from.ss, &fromlen);
11497- if (len < 0) {
11498- wpa_printf(MSG_ERROR, "DAS: recvfrom: %s", strerror(errno));
11499- return;
11500- }
11501-
11502- os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf));
11503- from_port = ntohs(from.sin.sin_port);
11504-
11505- wpa_printf(MSG_DEBUG, "DAS: Received %d bytes from %s:%d",
11506- len, abuf, from_port);
11507- if (das->client_addr.u.v4.s_addr &&
11508- das->client_addr.u.v4.s_addr != from.sin.sin_addr.s_addr) {
11509- wpa_printf(MSG_DEBUG, "DAS: Drop message from unknown client");
11510- return;
11511- }
11512-
11513- msg = radius_msg_parse(buf, len);
11514- if (msg == NULL) {
11515- wpa_printf(MSG_DEBUG, "DAS: Parsing incoming RADIUS packet "
11516- "from %s:%d failed", abuf, from_port);
11517- return;
11518- }
11519-
11520- if (wpa_debug_level <= MSG_MSGDUMP)
11521- radius_msg_dump(msg);
11522
11523 if (radius_msg_verify_das_req(msg, das->shared_secret,
11524 das->shared_secret_len,
developer05f3b2b2024-08-19 19:17:34 +080011525@@ -504,9 +478,8 @@ static void radius_das_receive(int sock, void *eloop_ctx, void *sock_ctx)
developer66e89bc2024-04-23 14:50:01 +080011526 radius_msg_dump(reply);
11527
11528 rbuf = radius_msg_get_buf(reply);
11529- res = sendto(das->sock, wpabuf_head(rbuf),
11530- wpabuf_len(rbuf), 0,
11531- (struct sockaddr *) &from.ss, fromlen);
11532+ res = sendto(das->port->sock, wpabuf_head(rbuf),
11533+ wpabuf_len(rbuf), 0, from, fromlen);
11534 if (res < 0) {
11535 wpa_printf(MSG_ERROR, "DAS: sendto(to %s:%d): %s",
11536 abuf, from_port, strerror(errno));
developer05f3b2b2024-08-19 19:17:34 +080011537@@ -518,6 +491,72 @@ fail:
developer66e89bc2024-04-23 14:50:01 +080011538 radius_msg_free(reply);
11539 }
11540
11541+static void radius_das_receive(int sock, void *eloop_ctx, void *sock_ctx)
11542+{
11543+ struct radius_das_port *p = eloop_ctx;
11544+ struct radius_das_data *das;
11545+ u8 buf[1500];
11546+ union {
11547+ struct sockaddr_storage ss;
11548+ struct sockaddr_in sin;
11549+#ifdef CONFIG_IPV6
11550+ struct sockaddr_in6 sin6;
11551+#endif /* CONFIG_IPV6 */
11552+ } from;
11553+ struct radius_msg *msg;
11554+ size_t nasid_len = 0;
11555+ u8 *nasid_buf = NULL;
11556+ char abuf[50];
11557+ int from_port = 0;
11558+ socklen_t fromlen;
11559+ int found = 0;
11560+ int len;
11561+
11562+ fromlen = sizeof(from);
11563+ len = recvfrom(sock, buf, sizeof(buf), 0,
11564+ (struct sockaddr *) &from.ss, &fromlen);
11565+ if (len < 0) {
11566+ wpa_printf(MSG_ERROR, "DAS: recvfrom: %s", strerror(errno));
11567+ return;
11568+ }
11569+
11570+ os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf));
11571+ from_port = ntohs(from.sin.sin_port);
11572+
11573+ msg = radius_msg_parse(buf, len);
11574+ if (msg == NULL) {
11575+ wpa_printf(MSG_DEBUG, "DAS: Parsing incoming RADIUS packet "
11576+ "from %s:%d failed", abuf, from_port);
11577+ return;
11578+ }
11579+
11580+ wpa_printf(MSG_DEBUG, "DAS: Received %d bytes from %s:%d",
11581+ len, abuf, from_port);
11582+
11583+ if (wpa_debug_level <= MSG_MSGDUMP)
11584+ radius_msg_dump(msg);
11585+
11586+ radius_msg_get_attr_ptr(msg, RADIUS_ATTR_NAS_IDENTIFIER,
11587+ &nasid_buf, &nasid_len, NULL);
11588+ dl_list_for_each(das, &p->das_data, struct radius_das_data, list) {
11589+ if (das->client_addr.u.v4.s_addr &&
11590+ das->client_addr.u.v4.s_addr != from.sin.sin_addr.s_addr)
11591+ continue;
11592+
11593+ if (das->nas_identifier && nasid_buf &&
11594+ (nasid_len != os_strlen(das->nas_identifier) ||
11595+ os_memcmp(das->nas_identifier, nasid_buf, nasid_len) != 0))
11596+ continue;
11597+
11598+ found = 1;
11599+ radius_das_receive_msg(das, msg, (struct sockaddr *)&from.ss,
11600+ fromlen, abuf, from_port);
11601+ }
11602+
11603+ if (!found)
11604+ wpa_printf(MSG_DEBUG, "DAS: Drop message from unknown client");
11605+}
11606+
11607
11608 static int radius_das_open_socket(int port)
11609 {
developer05f3b2b2024-08-19 19:17:34 +080011610@@ -543,6 +582,49 @@ static int radius_das_open_socket(int port)
developer66e89bc2024-04-23 14:50:01 +080011611 }
11612
11613
11614+static struct radius_das_port *
11615+radius_das_open_port(int port)
11616+{
11617+ struct radius_das_port *p;
11618+
11619+ dl_list_for_each(p, &das_ports, struct radius_das_port, list) {
11620+ if (p->port == port)
11621+ return p;
11622+ }
11623+
11624+ p = os_zalloc(sizeof(*p));
11625+ if (p == NULL)
11626+ return NULL;
11627+
11628+ dl_list_init(&p->das_data);
11629+ p->port = port;
11630+ p->sock = radius_das_open_socket(port);
11631+ if (p->sock < 0)
11632+ goto free_port;
11633+
11634+ if (eloop_register_read_sock(p->sock, radius_das_receive, p, NULL))
11635+ goto close_port;
11636+
11637+ dl_list_add(&das_ports, &p->list);
11638+
11639+ return p;
11640+
11641+close_port:
11642+ close(p->sock);
11643+free_port:
11644+ os_free(p);
11645+
11646+ return NULL;
11647+}
11648+
11649+static void radius_das_close_port(struct radius_das_port *p)
11650+{
11651+ dl_list_del(&p->list);
11652+ eloop_unregister_read_sock(p->sock);
11653+ close(p->sock);
11654+ free(p);
11655+}
11656+
11657 struct radius_das_data *
11658 radius_das_init(struct radius_das_conf *conf)
11659 {
developer05f3b2b2024-08-19 19:17:34 +080011660@@ -563,6 +645,8 @@ radius_das_init(struct radius_das_conf *conf)
developer66e89bc2024-04-23 14:50:01 +080011661 das->ctx = conf->ctx;
11662 das->disconnect = conf->disconnect;
11663 das->coa = conf->coa;
11664+ if (conf->nas_identifier)
11665+ das->nas_identifier = os_strdup(conf->nas_identifier);
11666
11667 os_memcpy(&das->client_addr, conf->client_addr,
11668 sizeof(das->client_addr));
developer05f3b2b2024-08-19 19:17:34 +080011669@@ -575,19 +659,15 @@ radius_das_init(struct radius_das_conf *conf)
developer66e89bc2024-04-23 14:50:01 +080011670 }
11671 das->shared_secret_len = conf->shared_secret_len;
11672
11673- das->sock = radius_das_open_socket(conf->port);
11674- if (das->sock < 0) {
11675+ das->port = radius_das_open_port(conf->port);
11676+ if (!das->port) {
11677 wpa_printf(MSG_ERROR, "Failed to open UDP socket for RADIUS "
11678 "DAS");
11679 radius_das_deinit(das);
11680 return NULL;
11681 }
11682
11683- if (eloop_register_read_sock(das->sock, radius_das_receive, das, NULL))
11684- {
11685- radius_das_deinit(das);
11686- return NULL;
11687- }
11688+ dl_list_add(&das->port->das_data, &das->list);
11689
11690 return das;
11691 }
developer05f3b2b2024-08-19 19:17:34 +080011692@@ -598,11 +678,14 @@ void radius_das_deinit(struct radius_das_data *das)
developer66e89bc2024-04-23 14:50:01 +080011693 if (das == NULL)
11694 return;
11695
11696- if (das->sock >= 0) {
11697- eloop_unregister_read_sock(das->sock);
11698- close(das->sock);
11699+ if (das->port) {
11700+ dl_list_del(&das->list);
11701+
11702+ if (dl_list_empty(&das->port->das_data))
11703+ radius_das_close_port(das->port);
11704 }
11705
11706+ os_free(das->nas_identifier);
11707 os_free(das->shared_secret);
11708 os_free(das);
11709 }
11710diff --git a/src/radius/radius_das.h b/src/radius/radius_das.h
11711index 233d662f6..80dc13fc8 100644
11712--- a/src/radius/radius_das.h
11713+++ b/src/radius/radius_das.h
11714@@ -44,6 +44,7 @@ struct radius_das_attrs {
11715 struct radius_das_conf {
11716 int port;
11717 const u8 *shared_secret;
11718+ const u8 *nas_identifier;
11719 size_t shared_secret_len;
11720 const struct hostapd_ip_addr *client_addr;
11721 unsigned int time_window;
11722diff --git a/src/radius/radius_server.c b/src/radius/radius_server.c
developer05f3b2b2024-08-19 19:17:34 +080011723index fa3691548..95a1cb994 100644
developer66e89bc2024-04-23 14:50:01 +080011724--- a/src/radius/radius_server.c
11725+++ b/src/radius/radius_server.c
11726@@ -63,6 +63,12 @@ struct radius_server_counters {
11727 u32 unknown_acct_types;
11728 };
11729
11730+struct radius_accept_attr {
11731+ u8 type;
11732+ u16 len;
11733+ void *data;
11734+};
11735+
11736 /**
11737 * struct radius_session - Internal RADIUS server data for a session
11738 */
11739@@ -90,7 +96,7 @@ struct radius_session {
11740 unsigned int macacl:1;
11741 unsigned int t_c_filtering:1;
11742
11743- struct hostapd_radius_attr *accept_attr;
11744+ struct radius_accept_attr *accept_attr;
11745
11746 u32 t_c_timestamp; /* Last read T&C timestamp from user DB */
11747 };
11748@@ -394,6 +400,7 @@ static void radius_server_session_free(struct radius_server_data *data,
11749 radius_msg_free(sess->last_reply);
11750 os_free(sess->username);
11751 os_free(sess->nas_ip);
11752+ os_free(sess->accept_attr);
11753 os_free(sess);
11754 data->num_sess--;
11755 }
11756@@ -554,6 +561,36 @@ radius_server_erp_find_key(struct radius_server_data *data, const char *keyname)
11757 }
11758 #endif /* CONFIG_ERP */
11759
11760+static struct radius_accept_attr *
11761+radius_server_copy_attr(const struct hostapd_radius_attr *data)
11762+{
11763+ const struct hostapd_radius_attr *attr;
11764+ struct radius_accept_attr *attr_new;
11765+ size_t data_size = 0;
11766+ void *data_buf;
11767+ int n_attr = 1;
11768+
11769+ for (attr = data; attr; attr = attr->next) {
11770+ n_attr++;
11771+ data_size += wpabuf_len(attr->val);
11772+ }
11773+
11774+ attr_new = os_zalloc(n_attr * sizeof(*attr) + data_size);
11775+ if (!attr_new)
11776+ return NULL;
11777+
11778+ data_buf = &attr_new[n_attr];
11779+ for (n_attr = 0, attr = data; attr; attr = attr->next) {
11780+ struct radius_accept_attr *cur = &attr_new[n_attr++];
11781+
11782+ cur->type = attr->type;
11783+ cur->len = wpabuf_len(attr->val);
11784+ cur->data = memcpy(data_buf, wpabuf_head(attr->val), cur->len);
11785+ data_buf += cur->len;
11786+ }
11787+
11788+ return attr_new;
11789+}
11790
11791 static struct radius_session *
11792 radius_server_get_new_session(struct radius_server_data *data,
11793@@ -607,7 +644,7 @@ radius_server_get_new_session(struct radius_server_data *data,
11794 eap_user_free(tmp);
11795 return NULL;
11796 }
11797- sess->accept_attr = tmp->accept_attr;
11798+ sess->accept_attr = radius_server_copy_attr(tmp->accept_attr);
11799 sess->macacl = tmp->macacl;
11800 eap_user_free(tmp);
11801
developer05f3b2b2024-08-19 19:17:34 +080011802@@ -1123,11 +1160,10 @@ radius_server_encapsulate_eap(struct radius_server_data *data,
developer66e89bc2024-04-23 14:50:01 +080011803 }
11804
11805 if (code == RADIUS_CODE_ACCESS_ACCEPT) {
11806- struct hostapd_radius_attr *attr;
11807- for (attr = sess->accept_attr; attr; attr = attr->next) {
11808- if (!radius_msg_add_attr(msg, attr->type,
11809- wpabuf_head(attr->val),
11810- wpabuf_len(attr->val))) {
11811+ struct radius_accept_attr *attr;
11812+ for (attr = sess->accept_attr; attr->data; attr++) {
11813+ if (!radius_msg_add_attr(msg, attr->type, attr->data,
11814+ attr->len)) {
11815 wpa_printf(MSG_ERROR, "Could not add RADIUS attribute");
11816 radius_msg_free(msg);
11817 return NULL;
developer05f3b2b2024-08-19 19:17:34 +080011818@@ -1221,11 +1257,10 @@ radius_server_macacl(struct radius_server_data *data,
developer66e89bc2024-04-23 14:50:01 +080011819 }
11820
11821 if (code == RADIUS_CODE_ACCESS_ACCEPT) {
11822- struct hostapd_radius_attr *attr;
11823- for (attr = sess->accept_attr; attr; attr = attr->next) {
11824- if (!radius_msg_add_attr(msg, attr->type,
11825- wpabuf_head(attr->val),
11826- wpabuf_len(attr->val))) {
11827+ struct radius_accept_attr *attr;
11828+ for (attr = sess->accept_attr; attr->data; attr++) {
11829+ if (!radius_msg_add_attr(msg, attr->type, attr->data,
11830+ attr->len)) {
11831 wpa_printf(MSG_ERROR, "Could not add RADIUS attribute");
11832 radius_msg_free(msg);
11833 return NULL;
developer05f3b2b2024-08-19 19:17:34 +080011834@@ -2527,7 +2562,7 @@ static int radius_server_get_eap_user(void *ctx, const u8 *identity,
developer66e89bc2024-04-23 14:50:01 +080011835 ret = data->get_eap_user(data->conf_ctx, identity, identity_len,
11836 phase2, user);
11837 if (ret == 0 && user) {
11838- sess->accept_attr = user->accept_attr;
11839+ sess->accept_attr = radius_server_copy_attr(user->accept_attr);
11840 sess->remediation = user->remediation;
11841 sess->macacl = user->macacl;
11842 sess->t_c_timestamp = user->t_c_timestamp;
11843diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
developer05f3b2b2024-08-19 19:17:34 +080011844index 52a4c7442..ce1aa60a9 100644
developer66e89bc2024-04-23 14:50:01 +080011845--- a/src/rsn_supp/wpa.c
11846+++ b/src/rsn_supp/wpa.c
developer05f3b2b2024-08-19 19:17:34 +080011847@@ -4153,6 +4153,8 @@ static u32 wpa_key_mgmt_suite(struct wpa_sm *sm)
developer66e89bc2024-04-23 14:50:01 +080011848 }
11849
11850
11851+#ifdef CONFIG_CTRL_IFACE_MIB
11852+
11853 #define RSN_SUITE "%02x-%02x-%02x-%d"
11854 #define RSN_SUITE_ARG(s) \
11855 ((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff
developer05f3b2b2024-08-19 19:17:34 +080011856@@ -4234,6 +4236,7 @@ int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen)
developer66e89bc2024-04-23 14:50:01 +080011857
11858 return (int) len;
11859 }
11860+#endif
11861 #endif /* CONFIG_CTRL_IFACE */
11862
11863
11864diff --git a/src/tls/Makefile b/src/tls/Makefile
11865index c84fbe859..e974a41f0 100644
11866--- a/src/tls/Makefile
11867+++ b/src/tls/Makefile
11868@@ -1,3 +1,10 @@
11869+LIB_OBJS= asn1.o
11870+
11871+ifneq ($(CONFIG_TLS),gnutls)
11872+ifneq ($(CONFIG_TLS),mbedtls)
11873+ifneq ($(CONFIG_TLS),openssl)
11874+ifneq ($(CONFIG_TLS),wolfssl)
11875+
11876 CFLAGS += -DCONFIG_INTERNAL_LIBTOMMATH
11877 CFLAGS += -DCONFIG_CRYPTO_INTERNAL
11878 CFLAGS += -DCONFIG_TLSV11
11879@@ -21,5 +28,9 @@ LIB_OBJS= \
11880 tlsv1_server_read.o \
11881 tlsv1_server_write.o \
11882 x509v3.o
11883+endif
11884+endif
11885+endif
11886+endif
11887
11888 include ../lib.rules
11889diff --git a/src/utils/eloop.c b/src/utils/eloop.c
11890index 00b0beff0..50dd1beda 100644
11891--- a/src/utils/eloop.c
11892+++ b/src/utils/eloop.c
11893@@ -77,6 +77,9 @@ struct eloop_sock_table {
11894 struct eloop_data {
11895 int max_sock;
11896
11897+ eloop_timeout_poll_handler timeout_poll_cb;
11898+ eloop_poll_handler poll_cb;
11899+
11900 size_t count; /* sum of all table counts */
11901 #ifdef CONFIG_ELOOP_POLL
11902 size_t max_pollfd_map; /* number of pollfds_map currently allocated */
11903@@ -1121,6 +1124,12 @@ void eloop_run(void)
11904 os_reltime_sub(&timeout->time, &now, &tv);
11905 else
11906 tv.sec = tv.usec = 0;
11907+ }
11908+
11909+ if (eloop.timeout_poll_cb && eloop.timeout_poll_cb(&tv, !!timeout))
11910+ timeout = (void *)1;
11911+
11912+ if (timeout) {
11913 #if defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL)
11914 timeout_ms = tv.sec * 1000 + tv.usec / 1000;
11915 #endif /* defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL) */
11916@@ -1190,7 +1199,8 @@ void eloop_run(void)
11917 eloop.exceptions.changed = 0;
11918
11919 eloop_process_pending_signals();
11920-
11921+ if (eloop.poll_cb)
11922+ eloop.poll_cb();
11923
11924 /* check if some registered timeouts have occurred */
11925 timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
11926@@ -1252,6 +1262,14 @@ out:
11927 return;
11928 }
11929
11930+int eloop_register_cb(eloop_poll_handler poll_cb,
11931+ eloop_timeout_poll_handler timeout_cb)
11932+{
11933+ eloop.poll_cb = poll_cb;
11934+ eloop.timeout_poll_cb = timeout_cb;
11935+
11936+ return 0;
11937+}
11938
11939 void eloop_terminate(void)
11940 {
11941diff --git a/src/utils/eloop.h b/src/utils/eloop.h
11942index 04ee6d183..5452ea589 100644
11943--- a/src/utils/eloop.h
11944+++ b/src/utils/eloop.h
11945@@ -65,6 +65,9 @@ typedef void (*eloop_timeout_handler)(void *eloop_ctx, void *user_ctx);
11946 */
11947 typedef void (*eloop_signal_handler)(int sig, void *signal_ctx);
11948
11949+typedef bool (*eloop_timeout_poll_handler)(struct os_reltime *tv, bool tv_set);
11950+typedef void (*eloop_poll_handler)(void);
11951+
11952 /**
11953 * eloop_init() - Initialize global event loop data
11954 * Returns: 0 on success, -1 on failure
11955@@ -73,6 +76,9 @@ typedef void (*eloop_signal_handler)(int sig, void *signal_ctx);
11956 */
11957 int eloop_init(void);
11958
11959+int eloop_register_cb(eloop_poll_handler poll_cb,
11960+ eloop_timeout_poll_handler timeout_cb);
11961+
11962 /**
11963 * eloop_register_read_sock - Register handler for read events
11964 * @sock: File descriptor number for the socket
11965@@ -320,6 +326,8 @@ int eloop_register_signal_reconfig(eloop_signal_handler handler,
11966 */
11967 int eloop_sock_requeue(void);
11968
11969+void eloop_add_uloop(void);
11970+
11971 /**
11972 * eloop_run - Start the event loop
11973 *
11974diff --git a/src/utils/uloop.c b/src/utils/uloop.c
11975new file mode 100644
11976index 000000000..c0d26db93
11977--- /dev/null
11978+++ b/src/utils/uloop.c
11979@@ -0,0 +1,64 @@
11980+#include <libubox/uloop.h>
11981+#include "includes.h"
11982+#include "common.h"
11983+#include "eloop.h"
11984+
11985+static void eloop_uloop_event_cb(int sock, void *eloop_ctx, void *sock_ctx)
11986+{
11987+}
11988+
11989+static void eloop_uloop_fd_cb(struct uloop_fd *fd, unsigned int events)
11990+{
11991+ unsigned int changed = events ^ fd->flags;
11992+
11993+ if (changed & ULOOP_READ) {
11994+ if (events & ULOOP_READ)
11995+ eloop_register_sock(fd->fd, EVENT_TYPE_READ, eloop_uloop_event_cb, fd, fd);
11996+ else
11997+ eloop_unregister_sock(fd->fd, EVENT_TYPE_READ);
11998+ }
11999+
12000+ if (changed & ULOOP_WRITE) {
12001+ if (events & ULOOP_WRITE)
12002+ eloop_register_sock(fd->fd, EVENT_TYPE_WRITE, eloop_uloop_event_cb, fd, fd);
12003+ else
12004+ eloop_unregister_sock(fd->fd, EVENT_TYPE_WRITE);
12005+ }
12006+}
12007+
12008+static bool uloop_timeout_poll_handler(struct os_reltime *tv, bool tv_set)
12009+{
12010+ struct os_reltime tv_uloop;
12011+ int timeout_ms = uloop_get_next_timeout();
12012+
12013+ if (timeout_ms < 0)
12014+ return false;
12015+
12016+ tv_uloop.sec = timeout_ms / 1000;
12017+ tv_uloop.usec = (timeout_ms % 1000) * 1000;
12018+
12019+ if (!tv_set || os_reltime_before(&tv_uloop, tv)) {
12020+ *tv = tv_uloop;
12021+ return true;
12022+ }
12023+
12024+ return false;
12025+}
12026+
12027+static void uloop_poll_handler(void)
12028+{
12029+ uloop_run_timeout(0);
12030+}
12031+
12032+void eloop_add_uloop(void)
12033+{
12034+ static bool init_done = false;
12035+
12036+ if (!init_done) {
12037+ uloop_init();
12038+ uloop_fd_set_cb = eloop_uloop_fd_cb;
12039+ init_done = true;
12040+ }
12041+
12042+ eloop_register_cb(uloop_poll_handler, uloop_timeout_poll_handler);
12043+}
12044diff --git a/src/utils/wpa_debug.c b/src/utils/wpa_debug.c
12045index 7f3dd185f..627575e39 100644
12046--- a/src/utils/wpa_debug.c
12047+++ b/src/utils/wpa_debug.c
12048@@ -26,6 +26,10 @@ static FILE *wpa_debug_tracing_file = NULL;
12049 #define WPAS_TRACE_PFX "wpas <%d>: "
12050 #endif /* CONFIG_DEBUG_LINUX_TRACING */
12051
12052+void (*wpa_printf_hook)(int level, const char *fmt, va_list ap);
12053+void (*wpa_hexdump_hook)(int level, const char *title, const void *buf,
12054+ size_t len);
12055+void (*wpa_netlink_hook)(int tx, const void *data, size_t len);
12056
12057 int wpa_debug_level = MSG_INFO;
12058 int wpa_debug_show_keys = 0;
12059@@ -206,10 +210,16 @@ void wpa_debug_close_linux_tracing(void)
12060 *
12061 * Note: New line '\n' is added to the end of the text when printing to stdout.
12062 */
12063-void wpa_printf(int level, const char *fmt, ...)
12064+void _wpa_printf(int level, const char *fmt, ...)
12065 {
12066 va_list ap;
12067
12068+ if (wpa_printf_hook) {
12069+ va_start(ap, fmt);
12070+ wpa_printf_hook(level, fmt, ap);
12071+ va_end(ap);
12072+ }
12073+
12074 if (level >= wpa_debug_level) {
12075 #ifdef CONFIG_ANDROID_LOG
12076 va_start(ap, fmt);
12077@@ -255,11 +265,14 @@ void wpa_printf(int level, const char *fmt, ...)
12078 }
12079
12080
12081-static void _wpa_hexdump(int level, const char *title, const u8 *buf,
12082+void _wpa_hexdump(int level, const char *title, const u8 *buf,
12083 size_t len, int show, int only_syslog)
12084 {
12085 size_t i;
12086
12087+ if (wpa_hexdump_hook)
12088+ wpa_hexdump_hook(level, title, buf, len);
12089+
12090 #ifdef CONFIG_DEBUG_LINUX_TRACING
12091 if (wpa_debug_tracing_file != NULL) {
12092 fprintf(wpa_debug_tracing_file,
12093@@ -382,19 +395,7 @@ static void _wpa_hexdump(int level, const char *title, const u8 *buf,
12094 #endif /* CONFIG_ANDROID_LOG */
12095 }
12096
12097-void wpa_hexdump(int level, const char *title, const void *buf, size_t len)
12098-{
12099- _wpa_hexdump(level, title, buf, len, 1, 0);
12100-}
12101-
12102-
12103-void wpa_hexdump_key(int level, const char *title, const void *buf, size_t len)
12104-{
12105- _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys, 0);
12106-}
12107-
12108-
12109-static void _wpa_hexdump_ascii(int level, const char *title, const void *buf,
12110+void _wpa_hexdump_ascii(int level, const char *title, const void *buf,
12111 size_t len, int show)
12112 {
12113 size_t i, llen;
12114@@ -507,20 +508,6 @@ file_done:
12115 }
12116
12117
12118-void wpa_hexdump_ascii(int level, const char *title, const void *buf,
12119- size_t len)
12120-{
12121- _wpa_hexdump_ascii(level, title, buf, len, 1);
12122-}
12123-
12124-
12125-void wpa_hexdump_ascii_key(int level, const char *title, const void *buf,
12126- size_t len)
12127-{
12128- _wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys);
12129-}
12130-
12131-
12132 #ifdef CONFIG_DEBUG_FILE
12133 static char *last_path = NULL;
12134 #endif /* CONFIG_DEBUG_FILE */
12135@@ -644,7 +631,7 @@ void wpa_msg_register_ifname_cb(wpa_msg_get_ifname_func func)
12136 }
12137
12138
12139-void wpa_msg(void *ctx, int level, const char *fmt, ...)
12140+void _wpa_msg(void *ctx, int level, const char *fmt, ...)
12141 {
12142 va_list ap;
12143 char *buf;
12144@@ -682,7 +669,7 @@ void wpa_msg(void *ctx, int level, const char *fmt, ...)
12145 }
12146
12147
12148-void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...)
12149+void _wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...)
12150 {
12151 va_list ap;
12152 char *buf;
12153diff --git a/src/utils/wpa_debug.h b/src/utils/wpa_debug.h
12154index 4c02ad3c7..854520bfe 100644
12155--- a/src/utils/wpa_debug.h
12156+++ b/src/utils/wpa_debug.h
12157@@ -11,6 +11,10 @@
12158
12159 #include "wpabuf.h"
12160
12161+extern void (*wpa_printf_hook)(int level, const char *fmt, va_list ap);
12162+extern void (*wpa_hexdump_hook)(int level, const char *title,
12163+ const void *buf, size_t len);
12164+extern void (*wpa_netlink_hook)(int tx, const void *data, size_t len);
12165 extern int wpa_debug_level;
12166 extern int wpa_debug_show_keys;
12167 extern int wpa_debug_timestamp;
12168@@ -51,6 +55,17 @@ void wpa_debug_close_file(void);
12169 void wpa_debug_setup_stdout(void);
12170 void wpa_debug_stop_log(void);
12171
12172+/* internal */
12173+void _wpa_hexdump(int level, const char *title, const u8 *buf,
12174+ size_t len, int show, int only_syslog);
12175+void _wpa_hexdump_ascii(int level, const char *title, const void *buf,
12176+ size_t len, int show);
12177+extern int wpa_debug_show_keys;
12178+
12179+#ifndef CONFIG_MSG_MIN_PRIORITY
12180+#define CONFIG_MSG_MIN_PRIORITY 0
12181+#endif
12182+
12183 /**
12184 * wpa_debug_printf_timestamp - Print timestamp for debug output
12185 *
12186@@ -71,9 +86,15 @@ void wpa_debug_print_timestamp(void);
12187 *
12188 * Note: New line '\n' is added to the end of the text when printing to stdout.
12189 */
12190-void wpa_printf(int level, const char *fmt, ...)
12191+void _wpa_printf(int level, const char *fmt, ...)
12192 PRINTF_FORMAT(2, 3);
12193
12194+#define wpa_printf(level, ...) \
12195+ do { \
12196+ if (level >= CONFIG_MSG_MIN_PRIORITY) \
12197+ _wpa_printf(level, __VA_ARGS__); \
12198+ } while(0)
12199+
12200 /**
12201 * wpa_hexdump - conditional hex dump
12202 * @level: priority level (MSG_*) of the message
12203@@ -85,7 +106,13 @@ PRINTF_FORMAT(2, 3);
12204 * output may be directed to stdout, stderr, and/or syslog based on
12205 * configuration. The contents of buf is printed out has hex dump.
12206 */
12207-void wpa_hexdump(int level, const char *title, const void *buf, size_t len);
12208+static inline void wpa_hexdump(int level, const char *title, const void *buf, size_t len)
12209+{
12210+ if (level < CONFIG_MSG_MIN_PRIORITY)
12211+ return;
12212+
12213+ _wpa_hexdump(level, title, buf, len, 1, 1);
12214+}
12215
12216 static inline void wpa_hexdump_buf(int level, const char *title,
12217 const struct wpabuf *buf)
12218@@ -107,7 +134,13 @@ static inline void wpa_hexdump_buf(int level, const char *title,
12219 * like wpa_hexdump(), but by default, does not include secret keys (passwords,
12220 * etc.) in debug output.
12221 */
12222-void wpa_hexdump_key(int level, const char *title, const void *buf, size_t len);
12223+static inline void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len)
12224+{
12225+ if (level < CONFIG_MSG_MIN_PRIORITY)
12226+ return;
12227+
12228+ _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys, 1);
12229+}
12230
12231 static inline void wpa_hexdump_buf_key(int level, const char *title,
12232 const struct wpabuf *buf)
12233@@ -129,8 +162,14 @@ static inline void wpa_hexdump_buf_key(int level, const char *title,
12234 * the hex numbers and ASCII characters (for printable range) are shown. 16
12235 * bytes per line will be shown.
12236 */
12237-void wpa_hexdump_ascii(int level, const char *title, const void *buf,
12238- size_t len);
12239+static inline void wpa_hexdump_ascii(int level, const char *title,
12240+ const u8 *buf, size_t len)
12241+{
12242+ if (level < CONFIG_MSG_MIN_PRIORITY)
12243+ return;
12244+
12245+ _wpa_hexdump_ascii(level, title, buf, len, 1);
12246+}
12247
12248 /**
12249 * wpa_hexdump_ascii_key - conditional hex dump, hide keys
12250@@ -146,8 +185,14 @@ void wpa_hexdump_ascii(int level, const char *title, const void *buf,
12251 * bytes per line will be shown. This works like wpa_hexdump_ascii(), but by
12252 * default, does not include secret keys (passwords, etc.) in debug output.
12253 */
12254-void wpa_hexdump_ascii_key(int level, const char *title, const void *buf,
12255- size_t len);
12256+static inline void wpa_hexdump_ascii_key(int level, const char *title,
12257+ const u8 *buf, size_t len)
12258+{
12259+ if (level < CONFIG_MSG_MIN_PRIORITY)
12260+ return;
12261+
12262+ _wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys);
12263+}
12264
12265 /*
12266 * wpa_dbg() behaves like wpa_msg(), but it can be removed from build to reduce
12267@@ -184,7 +229,12 @@ void wpa_hexdump_ascii_key(int level, const char *title, const void *buf,
12268 *
12269 * Note: New line '\n' is added to the end of the text when printing to stdout.
12270 */
12271-void wpa_msg(void *ctx, int level, const char *fmt, ...) PRINTF_FORMAT(3, 4);
12272+void _wpa_msg(void *ctx, int level, const char *fmt, ...) PRINTF_FORMAT(3, 4);
12273+#define wpa_msg(ctx, level, ...) \
12274+ do { \
12275+ if (level >= CONFIG_MSG_MIN_PRIORITY) \
12276+ _wpa_msg(ctx, level, __VA_ARGS__); \
12277+ } while(0)
12278
12279 /**
12280 * wpa_msg_ctrl - Conditional printf for ctrl_iface monitors
12281@@ -198,8 +248,13 @@ void wpa_msg(void *ctx, int level, const char *fmt, ...) PRINTF_FORMAT(3, 4);
12282 * attached ctrl_iface monitors. In other words, it can be used for frequent
12283 * events that do not need to be sent to syslog.
12284 */
12285-void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...)
12286+void _wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...)
12287 PRINTF_FORMAT(3, 4);
12288+#define wpa_msg_ctrl(ctx, level, ...) \
12289+ do { \
12290+ if (level >= CONFIG_MSG_MIN_PRIORITY) \
12291+ _wpa_msg_ctrl(ctx, level, __VA_ARGS__); \
12292+ } while(0)
12293
12294 /**
12295 * wpa_msg_global - Global printf for ctrl_iface monitors
12296diff --git a/tests/Makefile b/tests/Makefile
developer05f3b2b2024-08-19 19:17:34 +080012297index 8ec154bb3..25fdf9e00 100644
developer66e89bc2024-04-23 14:50:01 +080012298--- a/tests/Makefile
12299+++ b/tests/Makefile
developer05f3b2b2024-08-19 19:17:34 +080012300@@ -1,10 +1,12 @@
12301-ALL=test-base64 test-md4 test-milenage \
12302- test-rsa-sig-ver \
12303- test-sha1 \
12304- test-https test-https_server \
12305- test-sha256 test-aes test-x509v3 test-list test-rc4 \
developer66e89bc2024-04-23 14:50:01 +080012306+RUN_TESTS= \
12307+ test-list \
12308+ test-md4 test-rc4 test-sha1 test-sha256 \
12309+ test-milenage test-aes \
developer05f3b2b2024-08-19 19:17:34 +080012310+ test-crypto_module \
12311 test-bss
12312
developer66e89bc2024-04-23 14:50:01 +080012313+ALL=$(RUN_TESTS) test-base64 test-https test-https_server
12314+
12315 include ../src/build.rules
12316
12317 ifdef LIBFUZZER
developer05f3b2b2024-08-19 19:17:34 +080012318@@ -25,13 +27,27 @@ CFLAGS += -DCONFIG_IEEE80211R_AP
developer66e89bc2024-04-23 14:50:01 +080012319 CFLAGS += -DCONFIG_IEEE80211R
12320 CFLAGS += -DCONFIG_TDLS
12321
12322+# test-crypto_module
12323+CFLAGS += -DCONFIG_MODULE_TESTS
12324+CFLAGS += -DCONFIG_DPP
12325+#CFLAGS += -DCONFIG_DPP2
12326+#CFLAGS += -DCONFIG_DPP3
12327+CFLAGS += -DCONFIG_ECC
12328+CFLAGS += -DCONFIG_HMAC_SHA256_KDF
12329+CFLAGS += -DCONFIG_HMAC_SHA384_KDF
12330+CFLAGS += -DCONFIG_MESH
12331+CFLAGS += -DCONFIG_SHA256
12332+CFLAGS += -DCONFIG_SHA384
12333+CFLAGS += -DEAP_PSK
12334+CFLAGS += -DEAP_FAST
12335+
12336 CFLAGS += -I../src
12337 CFLAGS += -I../src/utils
12338
12339 SLIBS = ../src/utils/libutils.a
12340
12341-DLIBS = ../src/crypto/libcrypto.a \
12342- ../src/tls/libtls.a
12343+DLIBS = ../src/tls/libtls.a \
12344+ ../src/crypto/libcrypto.a
12345
12346 _OBJS_VAR := LLIBS
12347 include ../src/objs.mk
developer05f3b2b2024-08-19 19:17:34 +080012348@@ -43,12 +59,43 @@ include ../src/objs.mk
developer66e89bc2024-04-23 14:50:01 +080012349 LIBS = $(SLIBS) $(DLIBS)
12350 LLIBS = -Wl,--start-group $(DLIBS) -Wl,--end-group $(SLIBS)
12351
12352+ifeq ($(CONFIG_TLS),mbedtls)
12353+CFLAGS += -DCONFIG_TLS_MBEDTLS
12354+LLIBS += -lmbedtls -lmbedx509 -lmbedcrypto
12355+else
12356+ifeq ($(CONFIG_TLS),openssl)
12357+CFLAGS += -DCONFIG_TLS_OPENSSL
12358+LLIBS += -lssl -lcrypto
12359+else
12360+ifeq ($(CONFIG_TLS),gnutls)
12361+CFLAGS += -DCONFIG_TLS_GNUTLS
12362+LLIBS += -lgnutls -lgpg-error -lgcrypt
12363+else
12364+ifeq ($(CONFIG_TLS),wolfssl)
12365+CFLAGS += -DCONFIG_TLS_WOLFSSL
12366+LLIBS += -lwolfssl -lm
12367+else
12368+CFLAGS += -DCONFIG_TLS_INTERNAL
12369+CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER
12370+ALL += test-rsa-sig-ver
12371+ALL += test-x509v3
12372+clean-config_tls_internal:
12373+ rm -f test_x509v3_nist.out.*
12374+ rm -f test_x509v3_nist2.out.*
12375+endif
12376+endif
12377+endif
12378+endif
12379+
12380 # glibc < 2.17 needs -lrt for clock_gettime()
12381 LLIBS += -lrt
12382
12383 test-aes: $(call BUILDOBJ,test-aes.o) $(LIBS)
12384 $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS)
12385
12386+test-crypto_module: $(call BUILDOBJ,test-crypto_module.o) $(LIBS)
12387+ $(LDO) $(LDFLAGS) -o $@ $< $(LLIBS)
12388+
12389 test-base64: $(call BUILDOBJ,test-base64.o) $(LIBS)
12390 $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS)
12391
developer05f3b2b2024-08-19 19:17:34 +080012392@@ -141,18 +188,11 @@ test-bss: $(call BUILDOBJ,test-bss.o) $(WPA_OBJS) $(LIBS)
12393 $(LDO) $(LDFLAGS) -o $@ $< $(LLIBS) $(WPA_CFLAGS) $(WPA_OBJS) $(LIBS)
12394
12395 run-tests: $(ALL)
12396- ./test-aes
12397- ./test-list
12398- ./test-md4
12399- ./test-milenage
12400- ./test-rsa-sig-ver
12401- ./test-sha1
12402- ./test-sha256
12403- ./test-bss
developer66e89bc2024-04-23 14:50:01 +080012404+ @set -ex; for i in $(RUN_TESTS); do ./$$i; done
12405 @echo
12406 @echo All tests completed successfully.
12407
12408-clean: common-clean
12409+clean: common-clean clean-config_tls_internal
12410 rm -f *~
12411- rm -f test_x509v3_nist.out.*
12412- rm -f test_x509v3_nist2.out.*
12413+
12414+.PHONY: run-tests clean-config_tls_internal
12415diff --git a/tests/hwsim/example-hostapd.config b/tests/hwsim/example-hostapd.config
developer05f3b2b2024-08-19 19:17:34 +080012416index 210b7fb86..5f326da07 100644
developer66e89bc2024-04-23 14:50:01 +080012417--- a/tests/hwsim/example-hostapd.config
12418+++ b/tests/hwsim/example-hostapd.config
12419@@ -4,6 +4,7 @@ CONFIG_DRIVER_NONE=y
12420 CONFIG_DRIVER_NL80211=y
12421 CONFIG_RSN_PREAUTH=y
12422
12423+#CONFIG_TLS=mbedtls
12424 #CONFIG_TLS=internal
12425 #CONFIG_INTERNAL_LIBTOMMATH=y
12426 #CONFIG_INTERNAL_LIBTOMMATH_FAST=y
12427@@ -33,12 +34,7 @@ CONFIG_EAP_TNC=y
12428 CFLAGS += -DTNC_CONFIG_FILE=\"tnc/tnc_config\"
12429 LIBS += -rdynamic
12430 CONFIG_EAP_UNAUTH_TLS=y
12431-ifeq ($(CONFIG_TLS), openssl)
12432-CONFIG_EAP_PWD=y
12433-endif
12434-ifeq ($(CONFIG_TLS), wolfssl)
12435-CONFIG_EAP_PWD=y
12436-endif
12437+CONFIG_EAP_PWD=$(if $(filter openssl wolfssl mbedtls,$(CONFIG_TLS)),y,)
12438 CONFIG_EAP_EKE=y
12439 CONFIG_PKCS12=y
12440 CONFIG_RADIUS_SERVER=y
developer66e89bc2024-04-23 14:50:01 +080012441diff --git a/tests/hwsim/example-wpa_supplicant.config b/tests/hwsim/example-wpa_supplicant.config
developer05f3b2b2024-08-19 19:17:34 +080012442index 123f397e3..c69b1f9cd 100644
developer66e89bc2024-04-23 14:50:01 +080012443--- a/tests/hwsim/example-wpa_supplicant.config
12444+++ b/tests/hwsim/example-wpa_supplicant.config
12445@@ -2,6 +2,7 @@
12446
12447 CONFIG_TLS=openssl
12448 #CONFIG_TLS=wolfssl
12449+#CONFIG_TLS=mbedtls
12450 #CONFIG_TLS=internal
12451 #CONFIG_INTERNAL_LIBTOMMATH=y
12452 #CONFIG_INTERNAL_LIBTOMMATH_FAST=y
12453@@ -34,13 +35,7 @@ LIBS += -rdynamic
12454 CONFIG_EAP_FAST=y
12455 CONFIG_EAP_TEAP=y
12456 CONFIG_EAP_IKEV2=y
12457-
12458-ifeq ($(CONFIG_TLS), openssl)
12459-CONFIG_EAP_PWD=y
12460-endif
12461-ifeq ($(CONFIG_TLS), wolfssl)
12462-CONFIG_EAP_PWD=y
12463-endif
12464+CONFIG_EAP_PWD=$(if $(filter openssl wolfssl mbedtls,$(CONFIG_TLS)),y,)
12465
12466 CONFIG_USIM_SIMULATOR=y
12467 CONFIG_SIM_SIMULATOR=y
developer66e89bc2024-04-23 14:50:01 +080012468diff --git a/tests/hwsim/test_ap_eap.py b/tests/hwsim/test_ap_eap.py
developer05f3b2b2024-08-19 19:17:34 +080012469index f8e75b5fb..48e4dedcc 100644
developer66e89bc2024-04-23 14:50:01 +080012470--- a/tests/hwsim/test_ap_eap.py
12471+++ b/tests/hwsim/test_ap_eap.py
12472@@ -42,20 +42,42 @@ def check_eap_capa(dev, method):
12473 res = dev.get_capability("eap")
12474 if method not in res:
12475 raise HwsimSkip("EAP method %s not supported in the build" % method)
12476+ if method == "FAST" or method == "TEAP":
12477+ tls = dev.request("GET tls_library")
12478+ if tls.startswith("mbed TLS"):
12479+ raise HwsimSkip("EAP-%s not supported with this TLS library: " % method + tls)
12480
12481 def check_subject_match_support(dev):
12482 tls = dev.request("GET tls_library")
12483- if not tls.startswith("OpenSSL") and not tls.startswith("wolfSSL"):
12484+ if tls.startswith("OpenSSL"):
12485+ return
12486+ elif tls.startswith("wolfSSL"):
12487+ return
12488+ elif tls.startswith("mbed TLS"):
12489+ return
12490+ else:
12491 raise HwsimSkip("subject_match not supported with this TLS library: " + tls)
12492
12493 def check_check_cert_subject_support(dev):
12494 tls = dev.request("GET tls_library")
12495- if not tls.startswith("OpenSSL") and not tls.startswith("wolfSSL"):
12496+ if tls.startswith("OpenSSL"):
12497+ return
12498+ elif tls.startswith("wolfSSL"):
12499+ return
12500+ elif tls.startswith("mbed TLS"):
12501+ return
12502+ else:
12503 raise HwsimSkip("check_cert_subject not supported with this TLS library: " + tls)
12504
12505 def check_altsubject_match_support(dev):
12506 tls = dev.request("GET tls_library")
12507- if not tls.startswith("OpenSSL") and not tls.startswith("wolfSSL"):
12508+ if tls.startswith("OpenSSL"):
12509+ return
12510+ elif tls.startswith("wolfSSL"):
12511+ return
12512+ elif tls.startswith("mbed TLS"):
12513+ return
12514+ else:
12515 raise HwsimSkip("altsubject_match not supported with this TLS library: " + tls)
12516
12517 def check_domain_match(dev):
12518@@ -70,7 +92,13 @@ def check_domain_suffix_match(dev):
12519
12520 def check_domain_match_full(dev):
12521 tls = dev.request("GET tls_library")
12522- if not tls.startswith("OpenSSL") and not tls.startswith("wolfSSL"):
12523+ if tls.startswith("OpenSSL"):
12524+ return
12525+ elif tls.startswith("wolfSSL"):
12526+ return
12527+ elif tls.startswith("mbed TLS"):
12528+ return
12529+ else:
12530 raise HwsimSkip("domain_suffix_match requires full match with this TLS library: " + tls)
12531
12532 def check_cert_probe_support(dev):
12533@@ -79,8 +107,15 @@ def check_cert_probe_support(dev):
12534 raise HwsimSkip("Certificate probing not supported with this TLS library: " + tls)
12535
12536 def check_ext_cert_check_support(dev):
12537+ if not openssl_imported:
12538+ raise HwsimSkip("OpenSSL python method not available")
12539+
12540 tls = dev.request("GET tls_library")
12541- if not tls.startswith("OpenSSL"):
12542+ if tls.startswith("OpenSSL"):
12543+ return
12544+ elif tls.startswith("mbed TLS"):
12545+ return
12546+ else:
12547 raise HwsimSkip("ext_cert_check not supported with this TLS library: " + tls)
12548
12549 def check_ocsp_support(dev):
developer05f3b2b2024-08-19 19:17:34 +080012550@@ -91,14 +126,18 @@ def check_ocsp_support(dev):
developer66e89bc2024-04-23 14:50:01 +080012551 # raise HwsimSkip("OCSP not supported with this TLS library: " + tls)
12552 #if tls.startswith("wolfSSL"):
12553 # raise HwsimSkip("OCSP not supported with this TLS library: " + tls)
12554+ if tls.startswith("mbed TLS"):
12555+ raise HwsimSkip("OCSP not supported with this TLS library: " + tls)
12556
12557 def check_pkcs5_v15_support(dev):
12558 tls = dev.request("GET tls_library")
12559- if "BoringSSL" in tls or "GnuTLS" in tls:
12560+ if "BoringSSL" in tls or "GnuTLS" in tls or "mbed TLS" in tls:
12561 raise HwsimSkip("PKCS#5 v1.5 not supported with this TLS library: " + tls)
12562
12563 def check_tls13_support(dev):
developer05f3b2b2024-08-19 19:17:34 +080012564 tls = dev.request("GET tls_library")
12565+ if tls.startswith("mbed TLS"):
12566+ raise HwsimSkip("TLS v1.3 not supported")
12567 ok = ['run=OpenSSL 1.1.1', 'run=OpenSSL 3.0', 'run=OpenSSL 3.1',
12568 'run=OpenSSL 3.2', 'run=OpenSSL 3.3', 'wolfSSL']
12569 for s in ok:
12570@@ -122,11 +161,15 @@ def check_pkcs12_support(dev):
developer66e89bc2024-04-23 14:50:01 +080012571 # raise HwsimSkip("PKCS#12 not supported with this TLS library: " + tls)
12572 if tls.startswith("wolfSSL"):
12573 raise HwsimSkip("PKCS#12 not supported with this TLS library: " + tls)
12574+ if tls.startswith("mbed TLS"):
12575+ raise HwsimSkip("PKCS#12 not supported with this TLS library: " + tls)
12576
12577 def check_dh_dsa_support(dev):
12578 tls = dev.request("GET tls_library")
12579 if tls.startswith("internal"):
12580 raise HwsimSkip("DH DSA not supported with this TLS library: " + tls)
12581+ if tls.startswith("mbed TLS"):
12582+ raise HwsimSkip("DH DSA not supported with this TLS library: " + tls)
12583
12584 def check_ec_support(dev):
12585 tls = dev.request("GET tls_library")
developer05f3b2b2024-08-19 19:17:34 +080012586@@ -1741,7 +1784,7 @@ def test_ap_wpa2_eap_ttls_pap_subject_match(dev, apdev):
developer66e89bc2024-04-23 14:50:01 +080012587 eap_connect(dev[0], hapd, "TTLS", "pap user",
12588 anonymous_identity="ttls", password="password",
12589 ca_cert="auth_serv/ca.pem", phase2="auth=PAP",
12590- subject_match="/C=FI/O=w1.fi/CN=server.w1.fi",
12591+ check_cert_subject="/C=FI/O=w1.fi/CN=server.w1.fi",
12592 altsubject_match="EMAIL:noone@example.com;DNS:server.w1.fi;URI:http://example.com/")
12593 eap_reauth(dev[0], "TTLS")
12594
developer05f3b2b2024-08-19 19:17:34 +080012595@@ -2976,6 +3019,7 @@ def test_ap_wpa2_eap_tls_neg_domain_match(dev, apdev):
developer66e89bc2024-04-23 14:50:01 +080012596
12597 def test_ap_wpa2_eap_tls_neg_subject_match(dev, apdev):
12598 """WPA2-Enterprise negative test - subject mismatch"""
12599+ check_subject_match_support(dev[0])
12600 params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
12601 hostapd.add_ap(apdev[0], params)
12602 dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
developer05f3b2b2024-08-19 19:17:34 +080012603@@ -3036,6 +3080,7 @@ def test_ap_wpa2_eap_tls_neg_subject_match(dev, apdev):
developer66e89bc2024-04-23 14:50:01 +080012604
12605 def test_ap_wpa2_eap_tls_neg_altsubject_match(dev, apdev):
12606 """WPA2-Enterprise negative test - altsubject mismatch"""
12607+ check_altsubject_match_support(dev[0])
12608 params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
12609 hostapd.add_ap(apdev[0], params)
12610
developer05f3b2b2024-08-19 19:17:34 +080012611@@ -3582,7 +3627,7 @@ def test_ap_wpa2_eap_ikev2_oom(dev, apdev):
developer66e89bc2024-04-23 14:50:01 +080012612 dev[0].request("REMOVE_NETWORK all")
12613
12614 tls = dev[0].request("GET tls_library")
12615- if not tls.startswith("wolfSSL"):
12616+ if not tls.startswith("wolfSSL") and not tls.startswith("mbed TLS"):
12617 tests = [(1, "os_get_random;dh_init")]
12618 else:
12619 tests = [(1, "crypto_dh_init;dh_init")]
developer05f3b2b2024-08-19 19:17:34 +080012620@@ -4896,7 +4941,7 @@ def test_ap_wpa2_eap_tls_intermediate_ca(dev, apdev, params):
developer66e89bc2024-04-23 14:50:01 +080012621 params["private_key"] = "auth_serv/iCA-server/server.key"
12622 hostapd.add_ap(apdev[0], params)
12623 tls = dev[0].request("GET tls_library")
12624- if "GnuTLS" in tls or "wolfSSL" in tls:
12625+ if "GnuTLS" in tls or "wolfSSL" in tls or "mbed TLS" in tls:
12626 ca_cert = "auth_serv/iCA-user/ca-and-root.pem"
12627 client_cert = "auth_serv/iCA-user/user_and_ica.pem"
12628 else:
developer05f3b2b2024-08-19 19:17:34 +080012629@@ -4962,6 +5007,7 @@ def test_ap_wpa2_eap_tls_intermediate_ca_ocsp_sha1(dev, apdev, params):
developer66e89bc2024-04-23 14:50:01 +080012630 run_ap_wpa2_eap_tls_intermediate_ca_ocsp(dev, apdev, params, "-sha1")
12631
12632 def run_ap_wpa2_eap_tls_intermediate_ca_ocsp(dev, apdev, params, md):
12633+ check_ocsp_support(dev[0])
12634 params = int_eap_server_params()
12635 params["ca_cert"] = "auth_serv/iCA-server/ca-and-root.pem"
12636 params["server_cert"] = "auth_serv/iCA-server/server.pem"
developer05f3b2b2024-08-19 19:17:34 +080012637@@ -4971,7 +5017,7 @@ def run_ap_wpa2_eap_tls_intermediate_ca_ocsp(dev, apdev, params, md):
developer66e89bc2024-04-23 14:50:01 +080012638 try:
12639 hostapd.add_ap(apdev[0], params)
12640 tls = dev[0].request("GET tls_library")
12641- if "GnuTLS" in tls or "wolfSSL" in tls:
12642+ if "GnuTLS" in tls or "wolfSSL" in tls or "mbed TLS" in tls:
12643 ca_cert = "auth_serv/iCA-user/ca-and-root.pem"
12644 client_cert = "auth_serv/iCA-user/user_and_ica.pem"
12645 else:
developer05f3b2b2024-08-19 19:17:34 +080012646@@ -5007,7 +5053,7 @@ def run_ap_wpa2_eap_tls_intermediate_ca_ocsp_revoked(dev, apdev, params, md):
developer66e89bc2024-04-23 14:50:01 +080012647 try:
12648 hostapd.add_ap(apdev[0], params)
12649 tls = dev[0].request("GET tls_library")
12650- if "GnuTLS" in tls or "wolfSSL" in tls:
12651+ if "GnuTLS" in tls or "wolfSSL" in tls or "mbed TLS" in tls:
12652 ca_cert = "auth_serv/iCA-user/ca-and-root.pem"
12653 client_cert = "auth_serv/iCA-user/user_and_ica.pem"
12654 else:
developer05f3b2b2024-08-19 19:17:34 +080012655@@ -5057,7 +5103,7 @@ def test_ap_wpa2_eap_tls_intermediate_ca_ocsp_multi_missing_resp(dev, apdev, par
developer66e89bc2024-04-23 14:50:01 +080012656 try:
12657 hostapd.add_ap(apdev[0], params)
12658 tls = dev[0].request("GET tls_library")
12659- if "GnuTLS" in tls or "wolfSSL" in tls:
12660+ if "GnuTLS" in tls or "wolfSSL" in tls or "mbed TLS" in tls:
12661 ca_cert = "auth_serv/iCA-user/ca-and-root.pem"
12662 client_cert = "auth_serv/iCA-user/user_and_ica.pem"
12663 else:
developer05f3b2b2024-08-19 19:17:34 +080012664@@ -5124,7 +5170,7 @@ def test_ap_wpa2_eap_tls_intermediate_ca_ocsp_multi(dev, apdev, params):
developer66e89bc2024-04-23 14:50:01 +080012665
12666 hostapd.add_ap(apdev[0], params)
12667 tls = dev[0].request("GET tls_library")
12668- if "GnuTLS" in tls or "wolfSSL" in tls:
12669+ if "GnuTLS" in tls or "wolfSSL" in tls or "mbed TLS" in tls:
12670 ca_cert = "auth_serv/iCA-user/ca-and-root.pem"
12671 client_cert = "auth_serv/iCA-user/user_and_ica.pem"
12672 else:
developer05f3b2b2024-08-19 19:17:34 +080012673@@ -5382,6 +5428,7 @@ def test_ap_wpa2_eap_ttls_server_cert_eku_client_server(dev, apdev):
developer66e89bc2024-04-23 14:50:01 +080012674
12675 def test_ap_wpa2_eap_ttls_server_pkcs12(dev, apdev):
12676 """WPA2-Enterprise using EAP-TTLS and server PKCS#12 file"""
12677+ check_pkcs12_support(dev[0])
12678 skip_with_fips(dev[0])
12679 params = int_eap_server_params()
12680 del params["server_cert"]
developer05f3b2b2024-08-19 19:17:34 +080012681@@ -5394,6 +5441,7 @@ def test_ap_wpa2_eap_ttls_server_pkcs12(dev, apdev):
developer66e89bc2024-04-23 14:50:01 +080012682
12683 def test_ap_wpa2_eap_ttls_server_pkcs12_extra(dev, apdev):
12684 """EAP-TTLS and server PKCS#12 file with extra certs"""
12685+ check_pkcs12_support(dev[0])
12686 skip_with_fips(dev[0])
12687 params = int_eap_server_params()
12688 del params["server_cert"]
developer05f3b2b2024-08-19 19:17:34 +080012689@@ -5416,6 +5464,7 @@ def test_ap_wpa2_eap_ttls_dh_params_server(dev, apdev):
developer66e89bc2024-04-23 14:50:01 +080012690
12691 def test_ap_wpa2_eap_ttls_dh_params_dsa_server(dev, apdev):
12692 """WPA2-Enterprise using EAP-TTLS and alternative server dhparams (DSA)"""
12693+ check_dh_dsa_support(dev[0])
12694 params = int_eap_server_params()
12695 params["dh_file"] = "auth_serv/dsaparam.pem"
12696 hapd = hostapd.add_ap(apdev[0], params)
developer05f3b2b2024-08-19 19:17:34 +080012697@@ -5727,8 +5776,8 @@ def test_ap_wpa2_eap_non_ascii_identity2(dev, apdev):
developer66e89bc2024-04-23 14:50:01 +080012698 def test_openssl_cipher_suite_config_wpas(dev, apdev):
12699 """OpenSSL cipher suite configuration on wpa_supplicant"""
12700 tls = dev[0].request("GET tls_library")
12701- if not tls.startswith("OpenSSL"):
12702- raise HwsimSkip("TLS library is not OpenSSL: " + tls)
12703+ if not tls.startswith("OpenSSL") and not tls.startswith("mbed TLS"):
12704+ raise HwsimSkip("TLS library is not OpenSSL or mbed TLS: " + tls)
12705 params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
12706 hapd = hostapd.add_ap(apdev[0], params)
12707 eap_connect(dev[0], hapd, "TTLS", "pap user",
developer05f3b2b2024-08-19 19:17:34 +080012708@@ -5754,14 +5803,14 @@ def test_openssl_cipher_suite_config_wpas(dev, apdev):
developer66e89bc2024-04-23 14:50:01 +080012709 def test_openssl_cipher_suite_config_hapd(dev, apdev):
12710 """OpenSSL cipher suite configuration on hostapd"""
12711 tls = dev[0].request("GET tls_library")
12712- if not tls.startswith("OpenSSL"):
12713- raise HwsimSkip("wpa_supplicant TLS library is not OpenSSL: " + tls)
12714+ if not tls.startswith("OpenSSL") and not tls.startswith("mbed TLS"):
12715+ raise HwsimSkip("wpa_supplicant TLS library is not OpenSSL or mbed TLS: " + tls)
12716 params = int_eap_server_params()
12717 params['openssl_ciphers'] = "AES256"
12718 hapd = hostapd.add_ap(apdev[0], params)
12719 tls = hapd.request("GET tls_library")
12720- if not tls.startswith("OpenSSL"):
12721- raise HwsimSkip("hostapd TLS library is not OpenSSL: " + tls)
12722+ if not tls.startswith("OpenSSL") and not tls.startswith("mbed TLS"):
12723+ raise HwsimSkip("hostapd TLS library is not OpenSSL or mbed TLS: " + tls)
12724 eap_connect(dev[0], hapd, "TTLS", "pap user",
12725 anonymous_identity="ttls", password="password",
12726 ca_cert="auth_serv/ca.pem", phase2="auth=PAP")
developer05f3b2b2024-08-19 19:17:34 +080012727@@ -6207,13 +6256,17 @@ def test_ap_wpa2_eap_tls_versions(dev, apdev):
developer66e89bc2024-04-23 14:50:01 +080012728 check_tls_ver(dev[0], hapd,
12729 "tls_disable_tlsv1_0=1 tls_disable_tlsv1_1=1",
12730 "TLSv1.2")
12731- elif tls.startswith("internal"):
12732+ elif tls.startswith("internal") or tls.startswith("mbed TLS"):
12733 check_tls_ver(dev[0], hapd,
12734 "tls_disable_tlsv1_0=1 tls_disable_tlsv1_1=1", "TLSv1.2")
developer05f3b2b2024-08-19 19:17:34 +080012735- check_tls_ver(dev[1], hapd,
12736- "tls_disable_tlsv1_0=1 tls_disable_tlsv1_1=0 tls_disable_tlsv1_2=1", "TLSv1.1")
12737- check_tls_ver(dev[2], hapd,
12738- "tls_disable_tlsv1_0=0 tls_disable_tlsv1_1=1 tls_disable_tlsv1_2=1", "TLSv1")
developer66e89bc2024-04-23 14:50:01 +080012739+ if tls.startswith("mbed TLS"):
12740+ check_tls_ver(dev[2], hapd,
12741+ "tls_disable_tlsv1_0=0 tls_disable_tlsv1_1=1 tls_disable_tlsv1_2=1", "TLSv1.0")
12742+ else:
12743+ check_tls_ver(dev[1], hapd,
12744+ "tls_disable_tlsv1_0=1 tls_disable_tlsv1_1=0 tls_disable_tlsv1_2=1", "TLSv1.1")
12745+ check_tls_ver(dev[2], hapd,
12746+ "tls_disable_tlsv1_0=0 tls_disable_tlsv1_1=1 tls_disable_tlsv1_2=1", "TLSv1")
developer05f3b2b2024-08-19 19:17:34 +080012747 if "run=OpenSSL 1.1.1" in tls or "run=OpenSSL 3." in tls:
developer66e89bc2024-04-23 14:50:01 +080012748 check_tls_ver(dev[0], hapd,
12749 "tls_disable_tlsv1_0=1 tls_disable_tlsv1_1=1 tls_disable_tlsv1_2=1 tls_disable_tlsv1_3=0", "TLSv1.3")
developer05f3b2b2024-08-19 19:17:34 +080012750@@ -6235,6 +6288,11 @@ def test_ap_wpa2_eap_tls_versions_server(dev, apdev):
developer66e89bc2024-04-23 14:50:01 +080012751 tests = [("TLSv1", "[ENABLE-TLSv1.0][DISABLE-TLSv1.1][DISABLE-TLSv1.2][DISABLE-TLSv1.3]"),
12752 ("TLSv1.1", "[ENABLE-TLSv1.0][ENABLE-TLSv1.1][DISABLE-TLSv1.2][DISABLE-TLSv1.3]"),
12753 ("TLSv1.2", "[ENABLE-TLSv1.0][ENABLE-TLSv1.1][ENABLE-TLSv1.2][DISABLE-TLSv1.3]")]
12754+ tls = dev[0].request("GET tls_library")
12755+ if tls.startswith("mbed TLS"):
12756+ tests = [#("TLSv1.0", "[ENABLE-TLSv1.0][DISABLE-TLSv1.1][DISABLE-TLSv1.2][DISABLE-TLSv1.3]"),
12757+ #("TLSv1.1", "[ENABLE-TLSv1.0][ENABLE-TLSv1.1][DISABLE-TLSv1.2][DISABLE-TLSv1.3]"),
12758+ ("TLSv1.2", "[ENABLE-TLSv1.0][ENABLE-TLSv1.1][ENABLE-TLSv1.2][DISABLE-TLSv1.3]")]
12759 for exp, flags in tests:
12760 hapd.disable()
12761 hapd.set("tls_flags", flags)
developer05f3b2b2024-08-19 19:17:34 +080012762@@ -7305,6 +7363,7 @@ def test_ap_wpa2_eap_assoc_rsn(dev, apdev):
developer66e89bc2024-04-23 14:50:01 +080012763 def test_eap_tls_ext_cert_check(dev, apdev):
12764 """EAP-TLS and external server certification validation"""
12765 # With internal server certificate chain validation
12766+ check_ext_cert_check_support(dev[0])
12767 id = dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS",
12768 identity="tls user",
12769 ca_cert="auth_serv/ca.pem",
developer05f3b2b2024-08-19 19:17:34 +080012770@@ -7317,6 +7376,7 @@ def test_eap_tls_ext_cert_check(dev, apdev):
developer66e89bc2024-04-23 14:50:01 +080012771 def test_eap_ttls_ext_cert_check(dev, apdev):
12772 """EAP-TTLS and external server certification validation"""
12773 # Without internal server certificate chain validation
12774+ check_ext_cert_check_support(dev[0])
12775 id = dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
12776 identity="pap user", anonymous_identity="ttls",
12777 password="password", phase2="auth=PAP",
developer05f3b2b2024-08-19 19:17:34 +080012778@@ -7327,6 +7387,7 @@ def test_eap_ttls_ext_cert_check(dev, apdev):
developer66e89bc2024-04-23 14:50:01 +080012779 def test_eap_peap_ext_cert_check(dev, apdev):
12780 """EAP-PEAP and external server certification validation"""
12781 # With internal server certificate chain validation
12782+ check_ext_cert_check_support(dev[0])
12783 id = dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="PEAP",
12784 identity="user", anonymous_identity="peap",
12785 ca_cert="auth_serv/ca.pem",
developer05f3b2b2024-08-19 19:17:34 +080012786@@ -7337,6 +7398,7 @@ def test_eap_peap_ext_cert_check(dev, apdev):
developer66e89bc2024-04-23 14:50:01 +080012787
12788 def test_eap_fast_ext_cert_check(dev, apdev):
12789 """EAP-FAST and external server certification validation"""
12790+ check_ext_cert_check_support(dev[0])
12791 check_eap_capa(dev[0], "FAST")
12792 # With internal server certificate chain validation
12793 dev[0].request("SET blob fast_pac_auth_ext ")
developer05f3b2b2024-08-19 19:17:34 +080012794@@ -7351,10 +7413,6 @@ def test_eap_fast_ext_cert_check(dev, apdev):
developer66e89bc2024-04-23 14:50:01 +080012795 run_ext_cert_check(dev, apdev, id)
12796
12797 def run_ext_cert_check(dev, apdev, net_id):
12798- check_ext_cert_check_support(dev[0])
12799- if not openssl_imported:
12800- raise HwsimSkip("OpenSSL python method not available")
12801-
12802 params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
12803 hapd = hostapd.add_ap(apdev[0], params)
12804
12805diff --git a/tests/hwsim/test_ap_ft.py b/tests/hwsim/test_ap_ft.py
developer05f3b2b2024-08-19 19:17:34 +080012806index 13461f014..8ffb5042c 100644
developer66e89bc2024-04-23 14:50:01 +080012807--- a/tests/hwsim/test_ap_ft.py
12808+++ b/tests/hwsim/test_ap_ft.py
developer05f3b2b2024-08-19 19:17:34 +080012809@@ -2494,11 +2494,11 @@ def test_ap_ft_ap_oom5(dev, apdev):
developer66e89bc2024-04-23 14:50:01 +080012810 # This will fail to roam
12811 dev[0].roam(bssid1, check_bssid=False)
12812
12813- with fail_test(hapd1, 1, "sha256_prf_bits;wpa_pmk_r1_to_ptk;wpa_ft_process_auth_req"):
12814+ with fail_test(hapd1, 1, "sha256_prf;wpa_pmk_r1_to_ptk;wpa_ft_process_auth_req"):
12815 # This will fail to roam
12816 dev[0].roam(bssid1, check_bssid=False)
12817
12818- with fail_test(hapd1, 3, "wpa_pmk_r1_to_ptk;wpa_ft_process_auth_req"):
12819+ with fail_test(hapd1, 2, "wpa_pmk_r1_to_ptk;wpa_ft_process_auth_req"):
12820 # This will fail to roam
12821 dev[0].roam(bssid1, check_bssid=False)
12822
12823diff --git a/tests/hwsim/test_authsrv.py b/tests/hwsim/test_authsrv.py
12824index e0665bcb2..02ec301e5 100644
12825--- a/tests/hwsim/test_authsrv.py
12826+++ b/tests/hwsim/test_authsrv.py
12827@@ -156,9 +156,12 @@ def test_authsrv_oom(dev, apdev):
12828 if "FAIL" not in authsrv.request("ENABLE"):
12829 raise Exception("ENABLE succeeded during OOM")
12830
12831- with alloc_fail(authsrv, 1, "tls_init;authsrv_init"):
12832- if "FAIL" not in authsrv.request("ENABLE"):
12833- raise Exception("ENABLE succeeded during OOM")
12834+ # tls_mbedtls.c:tls_init() does not alloc memory (no alloc fail trigger)
12835+ tls = dev[0].request("GET tls_library")
12836+ if not tls.startswith("mbed TLS"):
12837+ with alloc_fail(authsrv, 1, "tls_init;authsrv_init"):
12838+ if "FAIL" not in authsrv.request("ENABLE"):
12839+ raise Exception("ENABLE succeeded during OOM")
12840
12841 for count in range(1, 3):
12842 with alloc_fail(authsrv, count, "eap_sim_db_init;authsrv_init"):
12843diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py
12844index 518983bd0..077de58c9 100644
12845--- a/tests/hwsim/test_dpp.py
12846+++ b/tests/hwsim/test_dpp.py
12847@@ -39,7 +39,8 @@ def check_dpp_capab(dev, brainpool=False, min_ver=1):
12848 raise HwsimSkip("DPP not supported")
12849 if brainpool:
12850 tls = dev.request("GET tls_library")
12851- if (not tls.startswith("OpenSSL") or "run=BoringSSL" in tls) and not tls.startswith("wolfSSL"):
12852+ if (not tls.startswith("OpenSSL") or "run=BoringSSL" in tls) and not tls.startswith("wolfSSL") \
12853+ and not tls.startswith("mbed TLS"):
12854 raise HwsimSkip("Crypto library does not support Brainpool curves: " + tls)
12855 capa = dev.request("GET_CAPABILITY dpp")
12856 ver = 1
12857@@ -3902,6 +3903,9 @@ def test_dpp_proto_auth_req_no_i_proto_key(dev, apdev):
12858
12859 def test_dpp_proto_auth_req_invalid_i_proto_key(dev, apdev):
12860 """DPP protocol testing - invalid I-proto key in Auth Req"""
12861+ tls = dev[0].request("GET tls_library")
12862+ if tls.startswith("mbed TLS"):
12863+ raise HwsimSkip("mbed TLS crypto_ecdh_set_peerkey() properly detects invalid key; no response")
12864 run_dpp_proto_auth_req_missing(dev, 66, "Invalid Initiator Protocol Key")
12865
12866 def test_dpp_proto_auth_req_no_i_nonce(dev, apdev):
12867@@ -3997,7 +4001,12 @@ def test_dpp_proto_auth_resp_no_r_proto_key(dev, apdev):
12868
12869 def test_dpp_proto_auth_resp_invalid_r_proto_key(dev, apdev):
12870 """DPP protocol testing - invalid R-Proto Key in Auth Resp"""
12871- run_dpp_proto_auth_resp_missing(dev, 67, "Invalid Responder Protocol Key")
12872+ tls = dev[0].request("GET tls_library")
12873+ if tls.startswith("mbed TLS"):
12874+ # mbed TLS crypto_ecdh_set_peerkey() properly detects invalid key
12875+ run_dpp_proto_auth_resp_missing(dev, 67, "Failed to derive ECDH shared secret")
12876+ else:
12877+ run_dpp_proto_auth_resp_missing(dev, 67, "Invalid Responder Protocol Key")
12878
12879 def test_dpp_proto_auth_resp_no_r_nonce(dev, apdev):
12880 """DPP protocol testing - no R-nonce in Auth Resp"""
12881@@ -4359,11 +4368,17 @@ def test_dpp_proto_pkex_exchange_resp_invalid_status(dev, apdev):
12882
12883 def test_dpp_proto_pkex_cr_req_invalid_bootstrap_key(dev, apdev):
12884 """DPP protocol testing - invalid Bootstrap Key in PKEX Commit-Reveal Request"""
12885+ tls = dev[0].request("GET tls_library")
12886+ if tls.startswith("mbed TLS"):
12887+ raise HwsimSkip("mbed TLS crypto_ecdh_set_peerkey() properly detects invalid key; no response")
12888 run_dpp_proto_pkex_req_missing(dev, 47,
12889 "Peer bootstrapping key is invalid")
12890
12891 def test_dpp_proto_pkex_cr_resp_invalid_bootstrap_key(dev, apdev):
12892 """DPP protocol testing - invalid Bootstrap Key in PKEX Commit-Reveal Response"""
12893+ tls = dev[0].request("GET tls_library")
12894+ if tls.startswith("mbed TLS"):
12895+ raise HwsimSkip("mbed TLS crypto_ecdh_set_peerkey() properly detects invalid key; no response")
12896 run_dpp_proto_pkex_resp_missing(dev, 48,
12897 "Peer bootstrapping key is invalid")
12898
12899diff --git a/tests/hwsim/test_erp.py b/tests/hwsim/test_erp.py
12900index d083993e8..262e9f095 100644
12901--- a/tests/hwsim/test_erp.py
12902+++ b/tests/hwsim/test_erp.py
12903@@ -12,7 +12,7 @@ import time
12904
12905 import hostapd
12906 from utils import *
12907-from test_ap_eap import int_eap_server_params, check_tls13_support
12908+from test_ap_eap import int_eap_server_params, check_tls13_support, check_eap_capa
12909 from test_ap_psk import find_wpas_process, read_process_memory, verify_not_present, get_key_locations
12910
12911 def test_erp_initiate_reauth_start(dev, apdev):
12912@@ -276,6 +276,7 @@ def test_erp_radius_eap_methods(dev, apdev):
12913 params['erp_domain'] = 'example.com'
12914 params['disable_pmksa_caching'] = '1'
12915 hapd = hostapd.add_ap(apdev[0], params)
12916+ tls = dev[0].request("GET tls_library")
12917
12918 erp_test(dev[0], hapd, eap="AKA", identity="0232010000000000@example.com",
12919 password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123")
12920@@ -289,7 +290,7 @@ def test_erp_radius_eap_methods(dev, apdev):
12921 password="5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123")
12922 erp_test(dev[0], hapd, eap="EKE", identity="erp-eke@example.com",
12923 password="hello")
12924- if "FAST" in eap_methods:
12925+ if "FAST" in eap_methods and check_eap_capa(dev[0], "FAST"):
12926 erp_test(dev[0], hapd, eap="FAST", identity="erp-fast@example.com",
12927 password="password", ca_cert="auth_serv/ca.pem",
12928 phase2="auth=GTC",
12929@@ -301,13 +302,14 @@ def test_erp_radius_eap_methods(dev, apdev):
12930 password="password")
12931 erp_test(dev[0], hapd, eap="PAX", identity="erp-pax@example.com",
12932 password_hex="0123456789abcdef0123456789abcdef")
12933- if "MSCHAPV2" in eap_methods:
12934+ if "MSCHAPV2" in eap_methods and check_eap_capa(dev[0], "MSCHAPV2"):
12935 erp_test(dev[0], hapd, eap="PEAP", identity="erp-peap@example.com",
12936 password="password", ca_cert="auth_serv/ca.pem",
12937 phase2="auth=MSCHAPV2")
12938- erp_test(dev[0], hapd, eap="TEAP", identity="erp-teap@example.com",
12939- password="password", ca_cert="auth_serv/ca.pem",
12940- phase2="auth=MSCHAPV2", pac_file="blob://teap_pac")
12941+ if check_eap_capa(dev[0], "TEAP"):
12942+ erp_test(dev[0], hapd, eap="TEAP", identity="erp-teap@example.com",
12943+ password="password", ca_cert="auth_serv/ca.pem",
12944+ phase2="auth=MSCHAPV2", pac_file="blob://teap_pac")
12945 erp_test(dev[0], hapd, eap="PSK", identity="erp-psk@example.com",
12946 password_hex="0123456789abcdef0123456789abcdef")
12947 if "PWD" in eap_methods:
12948@@ -640,7 +642,7 @@ def test_erp_local_errors(dev, apdev):
12949 dev[0].request("REMOVE_NETWORK all")
12950 dev[0].wait_disconnected()
12951
12952- for count in range(1, 6):
12953+ for count in range(1, 4):
12954 dev[0].request("ERP_FLUSH")
12955 with fail_test(dev[0], count, "hmac_sha256_kdf;eap_peer_erp_init"):
12956 dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
12957diff --git a/tests/hwsim/test_fils.py b/tests/hwsim/test_fils.py
developer05f3b2b2024-08-19 19:17:34 +080012958index 6f857243a..de65c57a7 100644
developer66e89bc2024-04-23 14:50:01 +080012959--- a/tests/hwsim/test_fils.py
12960+++ b/tests/hwsim/test_fils.py
developer05f3b2b2024-08-19 19:17:34 +080012961@@ -1477,6 +1477,10 @@ def check_ec_group(dev, group):
12962 tls = dev.request("GET tls_library")
12963 if tls.startswith("wolfSSL"):
12964 return
12965+ elif tls.startswith("mbed TLS"):
developer66e89bc2024-04-23 14:50:01 +080012966+ if int(group) == 27:
12967+ raise HwsimSkip("Brainpool EC group 27 not supported by mbed TLS")
developer05f3b2b2024-08-19 19:17:34 +080012968+ return
12969 if int(group) in [25]:
12970 if not (tls.startswith("OpenSSL") and ("build=OpenSSL 1.0.2" in tls or "build=OpenSSL 1.1" in tls or "build=OpenSSL 3." in tls) and ("run=OpenSSL 1.0.2" in tls or "run=OpenSSL 1.1" in tls or "run=OpenSSL 3." in tls)):
12971 raise HwsimSkip("EC group not supported")
developer66e89bc2024-04-23 14:50:01 +080012972diff --git a/tests/hwsim/test_pmksa_cache.py b/tests/hwsim/test_pmksa_cache.py
12973index 4a3b444ff..4f7f7f760 100644
12974--- a/tests/hwsim/test_pmksa_cache.py
12975+++ b/tests/hwsim/test_pmksa_cache.py
12976@@ -958,7 +958,7 @@ def test_pmksa_cache_preauth_wpas_oom(dev, apdev):
12977 eap_connect(dev[0], hapd, "PAX", "pax.user@example.com",
12978 password_hex="0123456789abcdef0123456789abcdef",
12979 bssid=apdev[0]['bssid'])
12980- for i in range(1, 11):
12981+ for i in range(1, 10):
12982 with alloc_fail(dev[0], i, "rsn_preauth_init"):
12983 res = dev[0].request("PREAUTH f2:11:22:33:44:55").strip()
12984 logger.info("Iteration %d - PREAUTH command results: %s" % (i, res))
12985@@ -966,7 +966,7 @@ def test_pmksa_cache_preauth_wpas_oom(dev, apdev):
12986 state = dev[0].request('GET_ALLOC_FAIL')
12987 if state.startswith('0:'):
12988 break
12989- time.sleep(0.05)
12990+ time.sleep(0.10)
12991
12992 def test_pmksa_cache_ctrl(dev, apdev):
12993 """PMKSA cache control interface operations"""
12994diff --git a/tests/hwsim/test_sae.py b/tests/hwsim/test_sae.py
developer05f3b2b2024-08-19 19:17:34 +080012995index 679db0e2d..4ea9bd6a4 100644
developer66e89bc2024-04-23 14:50:01 +080012996--- a/tests/hwsim/test_sae.py
12997+++ b/tests/hwsim/test_sae.py
12998@@ -178,6 +178,11 @@ def test_sae_groups(dev, apdev):
12999 if tls.startswith("OpenSSL") and "run=OpenSSL 1." in tls:
13000 logger.info("Add Brainpool EC groups since OpenSSL is new enough")
13001 sae_groups += [27, 28, 29, 30]
13002+ if tls.startswith("mbed TLS"):
13003+ # secp224k1 and secp224r1 (26) have prime p = 1 mod 4, and mbedtls
13004+ # does not have code to derive y from compressed format for those curves
13005+ sae_groups = [19, 25, 20, 21, 1, 2, 5, 14, 15, 16, 22, 23, 24]
13006+ sae_groups += [27, 28, 29, 30]
13007 heavy_groups = [14, 15, 16]
13008 suitable_groups = [15, 16, 17, 18, 19, 20, 21]
13009 groups = [str(g) for g in sae_groups]
developer05f3b2b2024-08-19 19:17:34 +080013010@@ -2232,6 +2237,8 @@ def run_sae_pwe_group(dev, apdev, group):
developer66e89bc2024-04-23 14:50:01 +080013011 logger.info("Add Brainpool EC groups since OpenSSL is new enough")
13012 elif tls.startswith("wolfSSL"):
13013 logger.info("Make sure Brainpool EC groups were enabled when compiling wolfSSL")
13014+ elif tls.startswith("mbed TLS"):
13015+ logger.info("Make sure Brainpool EC groups were enabled when compiling mbed TLS")
13016 else:
13017 raise HwsimSkip("Brainpool curve not supported")
13018 start_sae_pwe_ap(apdev[0], group, 2)
13019diff --git a/tests/hwsim/test_suite_b.py b/tests/hwsim/test_suite_b.py
developer05f3b2b2024-08-19 19:17:34 +080013020index ddd1c2ee7..a44f32955 100644
developer66e89bc2024-04-23 14:50:01 +080013021--- a/tests/hwsim/test_suite_b.py
13022+++ b/tests/hwsim/test_suite_b.py
13023@@ -27,6 +27,8 @@ def check_suite_b_tls_lib(dev, dhe=False, level128=False):
13024 return
13025 if tls.startswith("wolfSSL"):
13026 return
13027+ if tls.startswith("mbed TLS"):
13028+ return
13029 if not tls.startswith("OpenSSL"):
13030 raise HwsimSkip("TLS library not supported for Suite B: " + tls)
13031 supported = False
13032@@ -520,6 +522,7 @@ def test_suite_b_192_rsa_insufficient_dh(dev, apdev):
13033
13034 dev[0].connect("test-suite-b", key_mgmt="WPA-EAP-SUITE-B-192",
13035 ieee80211w="2",
13036+ openssl_ciphers="DHE-RSA-AES256-GCM-SHA384",
13037 phase1="tls_suiteb=1",
13038 eap="TLS", identity="tls user",
13039 ca_cert="auth_serv/rsa3072-ca.pem",
13040diff --git a/tests/hwsim/test_wpas_ctrl.py b/tests/hwsim/test_wpas_ctrl.py
developer05f3b2b2024-08-19 19:17:34 +080013041index cf6d3211e..cbf136eaf 100644
developer66e89bc2024-04-23 14:50:01 +080013042--- a/tests/hwsim/test_wpas_ctrl.py
13043+++ b/tests/hwsim/test_wpas_ctrl.py
13044@@ -1856,7 +1856,7 @@ def _test_wpas_ctrl_oom(dev):
13045 tls = dev[0].request("GET tls_library")
13046 if not tls.startswith("internal"):
13047 tests.append(('NFC_GET_HANDOVER_SEL NDEF P2P-CR-TAG', 'FAIL',
13048- 4, 'wpas_ctrl_nfc_get_handover_sel_p2p'))
13049+ 3, 'wpas_ctrl_nfc_get_handover_sel_p2p'))
13050 for cmd, exp, count, func in tests:
13051 with alloc_fail(dev[0], count, func):
13052 res = dev[0].request(cmd)
13053diff --git a/tests/hwsim/utils.py b/tests/hwsim/utils.py
13054index 7e3608284..b23c1ee0b 100644
13055--- a/tests/hwsim/utils.py
13056+++ b/tests/hwsim/utils.py
13057@@ -145,7 +145,13 @@ def check_imsi_privacy_support(dev):
13058
13059 def check_tls_tod(dev):
13060 tls = dev.request("GET tls_library")
13061- if not tls.startswith("OpenSSL") and not tls.startswith("internal"):
13062+ if tls.startswith("OpenSSL"):
13063+ return
13064+ elif tls.startswith("internal"):
13065+ return
13066+ elif tls.startswith("mbed TLS"):
13067+ return
13068+ else:
13069 raise HwsimSkip("TLS TOD-TOFU/STRICT not supported with this TLS library: " + tls)
13070
13071 def vht_supported():
13072diff --git a/tests/test-crypto_module.c b/tests/test-crypto_module.c
13073new file mode 100644
13074index 000000000..0f1156142
13075--- /dev/null
13076+++ b/tests/test-crypto_module.c
13077@@ -0,0 +1,16 @@
13078+/*
13079+ * crypto module tests - test program
13080+ * Copyright (c) 2022, Glenn Strauss <gstrauss@gluelogic.com>
13081+ *
13082+ * This software may be distributed under the terms of the BSD license.
13083+ * See README for more details.
13084+ */
13085+
13086+#include "utils/includes.h"
13087+#include "utils/module_tests.h"
13088+#include "crypto/crypto_module_tests.c"
13089+
13090+int main(int argc, char *argv[])
13091+{
13092+ return crypto_module_tests();
13093+}
13094diff --git a/tests/test-https.c b/tests/test-https.c
13095index a72e56f9d..e9df82f1d 100644
13096--- a/tests/test-https.c
13097+++ b/tests/test-https.c
13098@@ -75,7 +75,7 @@ static int https_client(int s, const char *path)
13099 struct tls_connection *conn;
13100 struct wpabuf *in, *out, *appl;
13101 int res = -1;
13102- int need_more_data;
13103+ int need_more_data = 0;
13104
13105 os_memset(&conf, 0, sizeof(conf));
13106 conf.event_cb = https_tls_event_cb;
13107@@ -93,8 +93,12 @@ static int https_client(int s, const char *path)
13108
13109 for (;;) {
13110 appl = NULL;
13111+#ifdef CONFIG_TLS_INTERNAL_SERVER
13112 out = tls_connection_handshake2(tls, conn, in, &appl,
13113 &need_more_data);
13114+#else
13115+ out = tls_connection_handshake(tls, conn, in, &appl);
13116+#endif
13117 wpabuf_free(in);
13118 in = NULL;
13119 if (out == NULL) {
13120@@ -152,11 +156,15 @@ static int https_client(int s, const char *path)
13121
13122 wpa_printf(MSG_INFO, "Reading HTTP response");
13123 for (;;) {
13124- int need_more_data;
13125+ int need_more_data = 0;
13126 in = https_recv(s);
13127 if (in == NULL)
13128 goto done;
13129+#ifdef CONFIG_TLS_INTERNAL_SERVER
13130 out = tls_connection_decrypt2(tls, conn, in, &need_more_data);
13131+#else
13132+ out = tls_connection_decrypt(tls, conn, in);
13133+#endif
13134 if (need_more_data)
13135 wpa_printf(MSG_DEBUG, "HTTP: Need more data");
13136 wpabuf_free(in);
13137diff --git a/tests/test-https_server.c b/tests/test-https_server.c
13138index 33b448682..9dcca5596 100644
13139--- a/tests/test-https_server.c
13140+++ b/tests/test-https_server.c
13141@@ -67,10 +67,12 @@ static struct wpabuf * https_recv(int s, int timeout_ms)
13142 }
13143
13144
13145+#ifdef CONFIG_TLS_INTERNAL_SERVER
13146 static void https_tls_log_cb(void *ctx, const char *msg)
13147 {
13148 wpa_printf(MSG_DEBUG, "TLS: %s", msg);
13149 }
13150+#endif
13151
13152
13153 static int https_server(int s)
13154@@ -79,7 +81,7 @@ static int https_server(int s)
13155 void *tls;
13156 struct tls_connection_params params;
13157 struct tls_connection *conn;
13158- struct wpabuf *in, *out, *appl;
13159+ struct wpabuf *in = NULL, *out = NULL, *appl = NULL;
13160 int res = -1;
13161
13162 os_memset(&conf, 0, sizeof(conf));
13163@@ -106,7 +108,9 @@ static int https_server(int s)
13164 return -1;
13165 }
13166
13167+#ifdef CONFIG_TLS_INTERNAL_SERVER
13168 tls_connection_set_log_cb(conn, https_tls_log_cb, NULL);
13169+#endif
13170
13171 for (;;) {
13172 in = https_recv(s, 5000);
13173@@ -147,12 +151,16 @@ static int https_server(int s)
13174
13175 wpa_printf(MSG_INFO, "Reading HTTP request");
13176 for (;;) {
13177- int need_more_data;
13178+ int need_more_data = 0;
13179
13180 in = https_recv(s, 5000);
13181 if (!in)
13182 goto done;
13183+#ifdef CONFIG_TLS_INTERNAL_SERVER
13184 out = tls_connection_decrypt2(tls, conn, in, &need_more_data);
13185+#else
13186+ out = tls_connection_decrypt(tls, conn, in);
13187+#endif
13188 wpabuf_free(in);
13189 in = NULL;
13190 if (need_more_data) {
13191diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
developer05f3b2b2024-08-19 19:17:34 +080013192index 743c8acd6..c40e8d70d 100644
developer66e89bc2024-04-23 14:50:01 +080013193--- a/wpa_supplicant/Makefile
13194+++ b/wpa_supplicant/Makefile
13195@@ -10,6 +10,7 @@ ALL += dbus/fi.w1.wpa_supplicant1.service
13196 EXTRA_TARGETS=dynamic_eap_methods
13197
13198 CONFIG_FILE=.config
13199+-include $(if $(MULTICALL),../hostapd/.config)
13200 include ../src/build.rules
13201
13202 ifdef CONFIG_BUILD_PASN_SO
developer05f3b2b2024-08-19 19:17:34 +080013203@@ -190,6 +191,25 @@ ifdef CONFIG_EAPOL_TEST
developer66e89bc2024-04-23 14:50:01 +080013204 CFLAGS += -Werror -DEAPOL_TEST
13205 endif
13206
13207+ifdef CONFIG_UBUS
13208+CFLAGS += -DUBUS_SUPPORT
13209+OBJS += ubus.o
13210+LIBS += -lubus
13211+NEED_ULOOP:=y
13212+endif
13213+
13214+ifdef CONFIG_UCODE
13215+CFLAGS += -DUCODE_SUPPORT
13216+OBJS += ../src/utils/ucode.o
13217+OBJS += ucode.o
13218+NEED_ULOOP:=y
13219+endif
13220+
13221+ifdef NEED_ULOOP
13222+OBJS += ../src/utils/uloop.o
13223+LIBS += -lubox
13224+endif
13225+
13226 ifdef CONFIG_CODE_COVERAGE
13227 CFLAGS += -O0 -fprofile-arcs -ftest-coverage -U_FORTIFY_SOURCE
13228 LIBS += -lgcov
developer05f3b2b2024-08-19 19:17:34 +080013229@@ -389,7 +409,9 @@ endif
developer66e89bc2024-04-23 14:50:01 +080013230 ifdef CONFIG_IBSS_RSN
13231 NEED_RSN_AUTHENTICATOR=y
13232 CFLAGS += -DCONFIG_IBSS_RSN
13233+ifndef MULTICALL
13234 CFLAGS += -DCONFIG_NO_VLAN
13235+endif
13236 OBJS += ibss_rsn.o
13237 endif
13238
developer05f3b2b2024-08-19 19:17:34 +080013239@@ -981,6 +1003,10 @@ ifdef CONFIG_DYNAMIC_EAP_METHODS
developer66e89bc2024-04-23 14:50:01 +080013240 CFLAGS += -DCONFIG_DYNAMIC_EAP_METHODS
13241 LIBS += -ldl -rdynamic
13242 endif
13243+else
13244+ ifdef MULTICALL
13245+ OBJS += ../src/eap_common/eap_common.o
13246+ endif
13247 endif
13248
13249 ifdef CONFIG_AP
developer05f3b2b2024-08-19 19:17:34 +080013250@@ -988,9 +1014,11 @@ NEED_EAP_COMMON=y
developer66e89bc2024-04-23 14:50:01 +080013251 NEED_RSN_AUTHENTICATOR=y
13252 CFLAGS += -DCONFIG_AP
13253 OBJS += ap.o
13254+ifndef MULTICALL
13255 CFLAGS += -DCONFIG_NO_RADIUS
13256 CFLAGS += -DCONFIG_NO_ACCOUNTING
13257 CFLAGS += -DCONFIG_NO_VLAN
13258+endif
13259 OBJS += ../src/ap/hostapd.o
13260 OBJS += ../src/ap/wpa_auth_glue.o
13261 OBJS += ../src/ap/utils.o
developer05f3b2b2024-08-19 19:17:34 +080013262@@ -1030,7 +1058,16 @@ ifdef CONFIG_FILS
developer66e89bc2024-04-23 14:50:01 +080013263 OBJS += ../src/ap/fils_hlp.o
13264 endif
13265 ifdef CONFIG_CTRL_IFACE
13266+ifdef CONFIG_CTRL_IFACE_MIB
13267+CFLAGS += -DCONFIG_CTRL_IFACE_MIB
13268+endif
13269 OBJS += ../src/ap/ctrl_iface_ap.o
13270+ifdef CONFIG_UBUS
13271+OBJS += ../src/ap/ubus.o
13272+endif
13273+ifdef CONFIG_UCODE
13274+OBJS += ../src/ap/ucode.o
13275+endif
13276 endif
13277
13278 CFLAGS += -DEAP_SERVER -DEAP_SERVER_IDENTITY
developer05f3b2b2024-08-19 19:17:34 +080013279@@ -1081,6 +1118,12 @@ endif
developer66e89bc2024-04-23 14:50:01 +080013280 ifdef CONFIG_HS20
13281 OBJS += ../src/ap/hs20.o
13282 endif
13283+else
13284+ ifdef MULTICALL
13285+ OBJS += ../src/eap_server/eap_server.o
13286+ OBJS += ../src/eap_server/eap_server_identity.o
13287+ OBJS += ../src/eap_server/eap_server_methods.o
13288+ endif
13289 endif
13290
13291 ifdef CONFIG_MBO
developer05f3b2b2024-08-19 19:17:34 +080013292@@ -1090,7 +1133,9 @@ NEED_GAS=y
developer66e89bc2024-04-23 14:50:01 +080013293 endif
13294
13295 ifdef NEED_RSN_AUTHENTICATOR
13296+ifndef MULTICALL
13297 CFLAGS += -DCONFIG_NO_RADIUS
13298+endif
13299 NEED_AES_WRAP=y
13300 OBJS += ../src/ap/wpa_auth.o
13301 OBJS += ../src/ap/wpa_auth_ie.o
developer05f3b2b2024-08-19 19:17:34 +080013302@@ -1189,6 +1234,7 @@ TLS_FUNCS=y
developer66e89bc2024-04-23 14:50:01 +080013303 endif
13304
13305 ifeq ($(CONFIG_TLS), wolfssl)
13306+CFLAGS += -DCONFIG_TLS_WOLFSSL
13307 ifdef TLS_FUNCS
13308 CFLAGS += -DWOLFSSL_DER_LOAD
13309 OBJS += ../src/crypto/tls_wolfssl.o
developer05f3b2b2024-08-19 19:17:34 +080013310@@ -1204,6 +1250,7 @@ LIBS_p += -lwolfssl -lm
developer66e89bc2024-04-23 14:50:01 +080013311 endif
13312
13313 ifeq ($(CONFIG_TLS), openssl)
13314+CFLAGS += -DCONFIG_TLS_OPENSSL
13315 CFLAGS += -DCRYPTO_RSA_OAEP_SHA256
13316 ifdef TLS_FUNCS
13317 CFLAGS += -DEAP_TLS_OPENSSL
developer05f3b2b2024-08-19 19:17:34 +080013318@@ -1230,7 +1277,28 @@ endif
developer66e89bc2024-04-23 14:50:01 +080013319 CFLAGS += -DTLS_DEFAULT_CIPHERS=\"$(CONFIG_TLS_DEFAULT_CIPHERS)\"
13320 endif
13321
13322+ifeq ($(CONFIG_TLS), mbedtls)
13323+CFLAGS += -DCONFIG_TLS_MBEDTLS
13324+ifndef CONFIG_CRYPTO
13325+CONFIG_CRYPTO=mbedtls
13326+endif
13327+ifdef TLS_FUNCS
13328+OBJS += ../src/crypto/tls_mbedtls.o
13329+LIBS += -lmbedtls -lmbedx509
13330+endif
13331+OBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o
13332+OBJS_p += ../src/crypto/crypto_$(CONFIG_CRYPTO).o
13333+OBJS_priv += ../src/crypto/crypto_$(CONFIG_CRYPTO).o
13334+ifeq ($(CONFIG_CRYPTO), mbedtls)
13335+LIBS += -lmbedcrypto
13336+LIBS_p += -lmbedcrypto
13337+# XXX: create a config option?
13338+CFLAGS += -DCRYPTO_RSA_OAEP_SHA256
13339+endif
13340+endif
13341+
13342 ifeq ($(CONFIG_TLS), gnutls)
13343+CFLAGS += -DCONFIG_TLS_GNUTLS
13344 ifndef CONFIG_CRYPTO
13345 # default to libgcrypt
13346 CONFIG_CRYPTO=gnutls
developer05f3b2b2024-08-19 19:17:34 +080013347@@ -1261,6 +1329,7 @@ endif
developer66e89bc2024-04-23 14:50:01 +080013348 endif
13349
13350 ifeq ($(CONFIG_TLS), internal)
13351+CFLAGS += -DCONFIG_TLS_INTERNAL
13352 ifndef CONFIG_CRYPTO
13353 CONFIG_CRYPTO=internal
13354 endif
developer05f3b2b2024-08-19 19:17:34 +080013355@@ -1341,6 +1410,7 @@ endif
developer66e89bc2024-04-23 14:50:01 +080013356 endif
13357
13358 ifeq ($(CONFIG_TLS), linux)
13359+CFLAGS += -DCONFIG_TLS_INTERNAL
13360 OBJS += ../src/crypto/crypto_linux.o
13361 OBJS_p += ../src/crypto/crypto_linux.o
13362 ifdef TLS_FUNCS
developer05f3b2b2024-08-19 19:17:34 +080013363@@ -1422,9 +1492,11 @@ endif
developer66e89bc2024-04-23 14:50:01 +080013364
13365 ifneq ($(CONFIG_TLS), openssl)
13366 ifneq ($(CONFIG_TLS), wolfssl)
13367+ifneq ($(CONFIG_TLS), mbedtls)
13368 NEED_INTERNAL_AES_WRAP=y
13369 endif
13370 endif
13371+endif
13372 ifdef CONFIG_OPENSSL_INTERNAL_AES_WRAP
13373 # Seems to be needed at least with BoringSSL
13374 NEED_INTERNAL_AES_WRAP=y
developer05f3b2b2024-08-19 19:17:34 +080013375@@ -1438,9 +1510,11 @@ endif
developer66e89bc2024-04-23 14:50:01 +080013376
13377 ifdef NEED_INTERNAL_AES_WRAP
13378 ifneq ($(CONFIG_TLS), linux)
13379+ifneq ($(CONFIG_TLS), mbedtls)
13380 AESOBJS += ../src/crypto/aes-unwrap.o
13381 endif
13382 endif
13383+endif
13384 ifdef NEED_AES_EAX
13385 AESOBJS += ../src/crypto/aes-eax.o
13386 NEED_AES_CTR=y
developer05f3b2b2024-08-19 19:17:34 +080013387@@ -1450,35 +1524,45 @@ AESOBJS += ../src/crypto/aes-siv.o
developer66e89bc2024-04-23 14:50:01 +080013388 NEED_AES_CTR=y
13389 endif
13390 ifdef NEED_AES_CTR
13391+ifneq ($(CONFIG_TLS), mbedtls)
13392 AESOBJS += ../src/crypto/aes-ctr.o
13393 endif
13394+endif
13395 ifdef NEED_AES_ENCBLOCK
13396+ifneq ($(CONFIG_TLS), mbedtls)
13397 AESOBJS += ../src/crypto/aes-encblock.o
13398 endif
13399+endif
13400 NEED_AES_ENC=y
13401 ifneq ($(CONFIG_TLS), openssl)
13402 ifneq ($(CONFIG_TLS), linux)
13403 ifneq ($(CONFIG_TLS), wolfssl)
13404+ifneq ($(CONFIG_TLS), mbedtls)
13405 AESOBJS += ../src/crypto/aes-omac1.o
13406 endif
13407 endif
13408 endif
13409+endif
13410 ifdef NEED_AES_WRAP
13411 NEED_AES_ENC=y
13412 ifdef NEED_INTERNAL_AES_WRAP
13413+ifneq ($(CONFIG_TLS), mbedtls)
13414 AESOBJS += ../src/crypto/aes-wrap.o
13415 endif
13416 endif
13417+endif
13418 ifdef NEED_AES_CBC
13419 NEED_AES_ENC=y
13420 ifneq ($(CONFIG_TLS), openssl)
13421 ifneq ($(CONFIG_TLS), linux)
13422 ifneq ($(CONFIG_TLS), wolfssl)
13423+ifneq ($(CONFIG_TLS), mbedtls)
13424 AESOBJS += ../src/crypto/aes-cbc.o
13425 endif
13426 endif
13427 endif
13428 endif
13429+endif
13430 ifdef NEED_AES_ENC
13431 ifdef CONFIG_INTERNAL_AES
13432 AESOBJS += ../src/crypto/aes-internal-enc.o
developer05f3b2b2024-08-19 19:17:34 +080013433@@ -1493,12 +1577,16 @@ ifneq ($(CONFIG_TLS), openssl)
developer66e89bc2024-04-23 14:50:01 +080013434 ifneq ($(CONFIG_TLS), linux)
13435 ifneq ($(CONFIG_TLS), gnutls)
13436 ifneq ($(CONFIG_TLS), wolfssl)
13437+ifneq ($(CONFIG_TLS), mbedtls)
13438 SHA1OBJS += ../src/crypto/sha1.o
13439 endif
13440 endif
13441 endif
13442 endif
13443+endif
13444+ifneq ($(CONFIG_TLS), mbedtls)
13445 SHA1OBJS += ../src/crypto/sha1-prf.o
13446+endif
13447 ifdef CONFIG_INTERNAL_SHA1
13448 SHA1OBJS += ../src/crypto/sha1-internal.o
13449 ifdef NEED_FIPS186_2_PRF
developer05f3b2b2024-08-19 19:17:34 +080013450@@ -1510,29 +1598,37 @@ CFLAGS += -DCONFIG_NO_PBKDF2
developer66e89bc2024-04-23 14:50:01 +080013451 else
13452 ifneq ($(CONFIG_TLS), openssl)
13453 ifneq ($(CONFIG_TLS), wolfssl)
13454+ifneq ($(CONFIG_TLS), mbedtls)
13455 SHA1OBJS += ../src/crypto/sha1-pbkdf2.o
13456 endif
13457 endif
13458 endif
13459+endif
13460 ifdef NEED_T_PRF
13461+ifneq ($(CONFIG_TLS), mbedtls)
13462 SHA1OBJS += ../src/crypto/sha1-tprf.o
13463 endif
13464+endif
13465 ifdef NEED_TLS_PRF
13466+ifneq ($(CONFIG_TLS), mbedtls)
13467 SHA1OBJS += ../src/crypto/sha1-tlsprf.o
13468 endif
13469 endif
13470+endif
13471
13472 ifndef CONFIG_FIPS
13473 ifneq ($(CONFIG_TLS), openssl)
13474 ifneq ($(CONFIG_TLS), linux)
13475 ifneq ($(CONFIG_TLS), gnutls)
13476 ifneq ($(CONFIG_TLS), wolfssl)
13477+ifneq ($(CONFIG_TLS), mbedtls)
13478 MD5OBJS += ../src/crypto/md5.o
13479 endif
13480 endif
13481 endif
13482 endif
13483 endif
13484+endif
13485 ifdef NEED_MD5
13486 ifdef CONFIG_INTERNAL_MD5
13487 MD5OBJS += ../src/crypto/md5-internal.o
developer05f3b2b2024-08-19 19:17:34 +080013488@@ -1587,12 +1683,17 @@ ifneq ($(CONFIG_TLS), openssl)
developer66e89bc2024-04-23 14:50:01 +080013489 ifneq ($(CONFIG_TLS), linux)
13490 ifneq ($(CONFIG_TLS), gnutls)
13491 ifneq ($(CONFIG_TLS), wolfssl)
13492+ifneq ($(CONFIG_TLS), mbedtls)
13493 SHA256OBJS += ../src/crypto/sha256.o
13494 endif
13495 endif
13496 endif
13497 endif
13498+endif
13499+
13500+ifneq ($(CONFIG_TLS), mbedtls)
13501 SHA256OBJS += ../src/crypto/sha256-prf.o
13502+endif
13503 ifdef CONFIG_INTERNAL_SHA256
13504 SHA256OBJS += ../src/crypto/sha256-internal.o
13505 endif
developer05f3b2b2024-08-19 19:17:34 +080013506@@ -1605,50 +1706,68 @@ CFLAGS += -DCONFIG_INTERNAL_SHA512
developer66e89bc2024-04-23 14:50:01 +080013507 SHA256OBJS += ../src/crypto/sha512-internal.o
13508 endif
13509 ifdef NEED_TLS_PRF_SHA256
13510+ifneq ($(CONFIG_TLS), mbedtls)
13511 SHA256OBJS += ../src/crypto/sha256-tlsprf.o
13512 endif
13513+endif
13514 ifdef NEED_TLS_PRF_SHA384
13515+ifneq ($(CONFIG_TLS), mbedtls)
13516 SHA256OBJS += ../src/crypto/sha384-tlsprf.o
13517 endif
13518+endif
13519 ifdef NEED_HMAC_SHA256_KDF
13520 CFLAGS += -DCONFIG_HMAC_SHA256_KDF
13521+ifneq ($(CONFIG_TLS), mbedtls)
13522 OBJS += ../src/crypto/sha256-kdf.o
13523 endif
13524+endif
13525 ifdef NEED_HMAC_SHA384_KDF
13526 CFLAGS += -DCONFIG_HMAC_SHA384_KDF
13527+ifneq ($(CONFIG_TLS), mbedtls)
13528 OBJS += ../src/crypto/sha384-kdf.o
13529 endif
13530+endif
13531 ifdef NEED_HMAC_SHA512_KDF
13532 CFLAGS += -DCONFIG_HMAC_SHA512_KDF
13533+ifneq ($(CONFIG_TLS), mbedtls)
13534 OBJS += ../src/crypto/sha512-kdf.o
13535 endif
13536+endif
13537 OBJS += $(SHA256OBJS)
13538 ifdef NEED_SHA384
13539 ifneq ($(CONFIG_TLS), openssl)
13540 ifneq ($(CONFIG_TLS), linux)
13541 ifneq ($(CONFIG_TLS), gnutls)
13542 ifneq ($(CONFIG_TLS), wolfssl)
13543+ifneq ($(CONFIG_TLS), mbedtls)
13544 OBJS += ../src/crypto/sha384.o
13545 endif
13546 endif
13547 endif
13548 endif
13549+endif
13550 CFLAGS += -DCONFIG_SHA384
13551+ifneq ($(CONFIG_TLS), mbedtls)
13552 OBJS += ../src/crypto/sha384-prf.o
13553 endif
13554+endif
13555 ifdef NEED_SHA512
13556 ifneq ($(CONFIG_TLS), openssl)
13557 ifneq ($(CONFIG_TLS), linux)
13558 ifneq ($(CONFIG_TLS), gnutls)
13559 ifneq ($(CONFIG_TLS), wolfssl)
13560+ifneq ($(CONFIG_TLS), mbedtls)
13561 OBJS += ../src/crypto/sha512.o
13562 endif
13563 endif
13564 endif
13565 endif
13566+endif
13567 CFLAGS += -DCONFIG_SHA512
13568+ifneq ($(CONFIG_TLS), mbedtls)
13569 OBJS += ../src/crypto/sha512-prf.o
13570 endif
13571+endif
13572
13573 ifdef NEED_ASN1
13574 OBJS += ../src/tls/asn1.o
developer05f3b2b2024-08-19 19:17:34 +080013575@@ -1823,10 +1942,12 @@ ifdef CONFIG_FIPS
developer66e89bc2024-04-23 14:50:01 +080013576 CFLAGS += -DCONFIG_FIPS
13577 ifneq ($(CONFIG_TLS), openssl)
13578 ifneq ($(CONFIG_TLS), wolfssl)
13579+ifneq ($(CONFIG_TLS), mbedtls)
13580 $(error CONFIG_FIPS=y requires CONFIG_TLS=openssl)
13581 endif
13582 endif
13583 endif
13584+endif
13585
13586 OBJS += $(SHA1OBJS) $(DESOBJS)
13587
developer05f3b2b2024-08-19 19:17:34 +080013588@@ -2004,32 +2125,38 @@ wpa_priv: $(BCHECK) $(OBJS_priv)
developer66e89bc2024-04-23 14:50:01 +080013589
13590 _OBJS_VAR := OBJS
13591 include ../src/objs.mk
13592+wpa_supplicant_multi.a: .config $(BCHECK) $(OBJS) $(EXTRA_progs)
13593+ $(Q)$(CC) -c -o wpa_supplicant_multi.o -Dmain=wpa_supplicant_main $(CFLAGS) main.c
13594+ @$(E) " CC " $<
13595+ @rm -f $@
13596+ @$(AR) cr $@ wpa_supplicant_multi.o $(OBJS)
13597+
13598 wpa_supplicant: $(BCHECK) $(OBJS) $(EXTRA_progs)
13599- $(Q)$(LDO) $(LDFLAGS) -o wpa_supplicant $(OBJS) $(LIBS) $(EXTRALIBS)
13600+ +$(Q)$(LDO) $(LDFLAGS) -o wpa_supplicant $(OBJS) $(LIBS) $(EXTRALIBS)
13601 @$(E) " LD " $@
13602
13603 _OBJS_VAR := OBJS_t
13604 include ../src/objs.mk
13605 eapol_test: $(OBJS_t)
13606- $(Q)$(LDO) $(LDFLAGS) -o eapol_test $(OBJS_t) $(LIBS)
13607+ +$(Q)$(LDO) $(LDFLAGS) -o eapol_test $(OBJS_t) $(LIBS)
13608 @$(E) " LD " $@
13609
13610 _OBJS_VAR := OBJS_t2
13611 include ../src/objs.mk
13612 preauth_test: $(OBJS_t2)
13613- $(Q)$(LDO) $(LDFLAGS) -o preauth_test $(OBJS_t2) $(LIBS)
13614+ +$(Q)$(LDO) $(LDFLAGS) -o preauth_test $(OBJS_t2) $(LIBS)
13615 @$(E) " LD " $@
13616
13617 _OBJS_VAR := OBJS_p
13618 include ../src/objs.mk
13619 wpa_passphrase: $(OBJS_p)
13620- $(Q)$(LDO) $(LDFLAGS) -o wpa_passphrase $(OBJS_p) $(LIBS_p) $(LIBS)
13621+ +$(Q)$(LDO) $(LDFLAGS) -o wpa_passphrase $(OBJS_p) $(LIBS_p) $(LIBS)
13622 @$(E) " LD " $@
13623
13624 _OBJS_VAR := OBJS_c
13625 include ../src/objs.mk
13626 wpa_cli: $(OBJS_c)
13627- $(Q)$(LDO) $(LDFLAGS) -o wpa_cli $(OBJS_c) $(LIBS_c)
13628+ +$(Q)$(LDO) $(LDFLAGS) -o wpa_cli $(OBJS_c) $(LIBS_c)
13629 @$(E) " LD " $@
13630
13631 LIBCTRL += ../src/common/wpa_ctrl.o
developer05f3b2b2024-08-19 19:17:34 +080013632@@ -2136,6 +2263,12 @@ eap_gpsk.so: $(SRC_EAP_GPSK)
developer66e89bc2024-04-23 14:50:01 +080013633 $(Q)sed -e 's|\@BINDIR\@|$(BINDIR)|g' $< >$@
13634 @$(E) " sed" $<
13635
13636+dump_cflags:
13637+ @printf "%s " "$(CFLAGS)"
13638+
13639+dump_ldflags:
13640+ @printf "%s " "$(LDFLAGS) $(LIBS) $(EXTRALIBS)"
13641+
13642 wpa_supplicant.exe: wpa_supplicant
13643 mv -f $< $@
13644 wpa_cli.exe: wpa_cli
13645diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
developer05f3b2b2024-08-19 19:17:34 +080013646index 69a0e5ee1..7e8c97c38 100644
developer66e89bc2024-04-23 14:50:01 +080013647--- a/wpa_supplicant/ap.c
13648+++ b/wpa_supplicant/ap.c
13649@@ -1520,7 +1520,7 @@ int wpas_ap_wps_nfc_report_handover(struct wpa_supplicant *wpa_s,
13650 #endif /* CONFIG_WPS */
13651
13652
13653-#ifdef CONFIG_CTRL_IFACE
13654+#if defined(CONFIG_CTRL_IFACE) && defined(CONFIG_CTRL_IFACE_MIB)
13655
13656 int ap_ctrl_iface_sta_first(struct wpa_supplicant *wpa_s,
13657 char *buf, size_t buflen)
developer05f3b2b2024-08-19 19:17:34 +080013658@@ -1846,17 +1846,37 @@ int ap_switch_channel(struct wpa_supplicant *wpa_s,
developer66e89bc2024-04-23 14:50:01 +080013659
13660
13661 #ifdef CONFIG_CTRL_IFACE
13662+
13663+static int __ap_ctrl_iface_chanswitch(struct hostapd_iface *iface,
13664+ struct csa_settings *settings)
13665+{
13666+#ifdef NEED_AP_MLME
13667+ if (!iface || !iface->bss[0])
13668+ return 0;
13669+
13670+ return hostapd_switch_channel(iface->bss[0], settings);
13671+#else
13672+ return -1;
13673+#endif
13674+}
13675+
13676+
13677 int ap_ctrl_iface_chanswitch(struct wpa_supplicant *wpa_s, const char *pos)
13678 {
13679 struct csa_settings settings;
13680 int ret = hostapd_parse_csa_settings(pos, &settings);
13681
developer05f3b2b2024-08-19 19:17:34 +080013682- if (ret)
13683- return ret;
developer66e89bc2024-04-23 14:50:01 +080013684+ if (!(wpa_s->ap_iface && wpa_s->ap_iface->bss[0]) &&
13685+ !(wpa_s->ifmsh && wpa_s->ifmsh->bss[0]))
13686+ return -1;
developer05f3b2b2024-08-19 19:17:34 +080013687
13688 settings.link_id = -1;
13689
13690- return ap_switch_channel(wpa_s, &settings);
developer66e89bc2024-04-23 14:50:01 +080013691+ ret = __ap_ctrl_iface_chanswitch(wpa_s->ap_iface, &settings);
developer05f3b2b2024-08-19 19:17:34 +080013692+ if (ret)
13693+ return ret;
13694+
13695+ return __ap_ctrl_iface_chanswitch(wpa_s->ifmsh, &settings);
13696 }
13697 #endif /* CONFIG_CTRL_IFACE */
developer66e89bc2024-04-23 14:50:01 +080013698
13699diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
developer05f3b2b2024-08-19 19:17:34 +080013700index b02b694a3..dc4b0636a 100644
developer66e89bc2024-04-23 14:50:01 +080013701--- a/wpa_supplicant/config.c
13702+++ b/wpa_supplicant/config.c
13703@@ -18,6 +18,7 @@
13704 #include "eap_peer/eap.h"
13705 #include "p2p/p2p.h"
13706 #include "fst/fst.h"
13707+#include "ap/sta_info.h"
13708 #include "config.h"
13709
13710
13711@@ -2421,6 +2422,97 @@ static char * wpa_config_write_mac_value(const struct parse_data *data,
13712 #endif /* NO_CONFIG_WRITE */
13713
13714
13715+static int wpa_config_parse_mcast_rate(const struct parse_data *data,
13716+ struct wpa_ssid *ssid, int line,
13717+ const char *value)
13718+{
13719+ ssid->mcast_rate = (int)(strtod(value, NULL) * 10);
13720+
13721+ return 0;
13722+}
13723+
13724+#ifndef NO_CONFIG_WRITE
13725+static char * wpa_config_write_mcast_rate(const struct parse_data *data,
13726+ struct wpa_ssid *ssid)
13727+{
13728+ char *value;
13729+ int res;
13730+
13731+ if (!ssid->mcast_rate == 0)
13732+ return NULL;
13733+
13734+ value = os_malloc(6); /* longest: 300.0 */
13735+ if (value == NULL)
13736+ return NULL;
13737+ res = os_snprintf(value, 5, "%.1f", (double)ssid->mcast_rate / 10);
13738+ if (res < 0) {
13739+ os_free(value);
13740+ return NULL;
13741+ }
13742+ return value;
13743+}
13744+#endif /* NO_CONFIG_WRITE */
13745+
13746+static int wpa_config_parse_rates(const struct parse_data *data,
13747+ struct wpa_ssid *ssid, int line,
13748+ const char *value)
13749+{
13750+ int i;
13751+ char *pos, *r, *sptr, *end;
13752+ double rate;
13753+
13754+ pos = (char *)value;
13755+ r = strtok_r(pos, ",", &sptr);
13756+ i = 0;
13757+ while (pos && i < WLAN_SUPP_RATES_MAX) {
13758+ rate = 0.0;
13759+ if (r)
13760+ rate = strtod(r, &end);
13761+ ssid->rates[i] = rate * 2;
13762+ if (*end != '\0' || rate * 2 != ssid->rates[i])
13763+ return 1;
13764+
13765+ i++;
13766+ r = strtok_r(NULL, ",", &sptr);
13767+ }
13768+
13769+ return 0;
13770+}
13771+
13772+#ifndef NO_CONFIG_WRITE
13773+static char * wpa_config_write_rates(const struct parse_data *data,
13774+ struct wpa_ssid *ssid)
13775+{
13776+ char *value, *pos;
13777+ int res, i;
13778+
13779+ if (ssid->rates[0] <= 0)
13780+ return NULL;
13781+
13782+ value = os_malloc(6 * WLAN_SUPP_RATES_MAX + 1);
13783+ if (value == NULL)
13784+ return NULL;
13785+ pos = value;
13786+ for (i = 0; i < WLAN_SUPP_RATES_MAX - 1; i++) {
13787+ res = os_snprintf(pos, 6, "%.1f,", (double)ssid->rates[i] / 2);
13788+ if (res < 0) {
13789+ os_free(value);
13790+ return NULL;
13791+ }
13792+ pos += res;
13793+ }
13794+ res = os_snprintf(pos, 6, "%.1f",
13795+ (double)ssid->rates[WLAN_SUPP_RATES_MAX - 1] / 2);
13796+ if (res < 0) {
13797+ os_free(value);
13798+ return NULL;
13799+ }
13800+
13801+ value[6 * WLAN_SUPP_RATES_MAX] = '\0';
13802+ return value;
13803+}
13804+#endif /* NO_CONFIG_WRITE */
13805+
13806 /* Helper macros for network block parser */
13807
13808 #ifdef OFFSET
13809@@ -2639,6 +2731,7 @@ static const struct parse_data ssid_fields[] = {
13810 #else /* CONFIG_MESH */
13811 { INT_RANGE(mode, 0, 4) },
13812 #endif /* CONFIG_MESH */
13813+ { INT_RANGE(noscan, 0, 1) },
13814 { INT_RANGE(proactive_key_caching, 0, 1) },
13815 { INT_RANGE(disabled, 0, 2) },
13816 { STR(id_str) },
13817@@ -2712,6 +2805,8 @@ static const struct parse_data ssid_fields[] = {
13818 { INT(ap_max_inactivity) },
13819 { INT(dtim_period) },
13820 { INT(beacon_int) },
13821+ { FUNC(rates) },
13822+ { FUNC(mcast_rate) },
13823 #ifdef CONFIG_MACSEC
13824 { INT_RANGE(macsec_policy, 0, 1) },
13825 { INT_RANGE(macsec_integ_only, 0, 1) },
13826diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
developer05f3b2b2024-08-19 19:17:34 +080013827index fd8eafe2b..5ce616129 100644
developer66e89bc2024-04-23 14:50:01 +080013828--- a/wpa_supplicant/config_file.c
13829+++ b/wpa_supplicant/config_file.c
13830@@ -326,8 +326,13 @@ struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp,
13831 while (cred_tail && cred_tail->next)
13832 cred_tail = cred_tail->next;
13833
13834+ if (!strncmp(name, "data:", 5)) {
13835+ f = fmemopen((void *)(name + 5), strlen(name + 5), "r");
13836+ name = "<inline>";
13837+ } else {
13838+ f = fopen(name, "r");
13839+ }
13840 wpa_printf(MSG_DEBUG, "Reading configuration file '%s'", name);
13841- f = fopen(name, "r");
13842 if (f == NULL) {
13843 wpa_printf(MSG_ERROR, "Failed to open config file '%s', "
13844 "error: %s", name, strerror(errno));
13845@@ -775,6 +780,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
13846 #endif /* IEEE8021X_EAPOL */
13847 INT(mode);
13848 INT(no_auto_peer);
13849+ INT(noscan);
13850 INT(mesh_fwding);
13851 INT(frequency);
13852 INT(enable_edmg);
13853diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
developer05f3b2b2024-08-19 19:17:34 +080013854index d64c30508..872bcc270 100644
developer66e89bc2024-04-23 14:50:01 +080013855--- a/wpa_supplicant/config_ssid.h
13856+++ b/wpa_supplicant/config_ssid.h
developer05f3b2b2024-08-19 19:17:34 +080013857@@ -879,6 +879,9 @@ struct wpa_ssid {
developer66e89bc2024-04-23 14:50:01 +080013858 */
13859 void *parent_cred;
13860
13861+ unsigned char rates[WLAN_SUPP_RATES_MAX];
13862+ double mcast_rate;
13863+
13864 #ifdef CONFIG_MACSEC
13865 /**
13866 * macsec_policy - Determines the policy for MACsec secure session
developer05f3b2b2024-08-19 19:17:34 +080013867@@ -1035,6 +1038,8 @@ struct wpa_ssid {
developer66e89bc2024-04-23 14:50:01 +080013868 */
13869 int no_auto_peer;
13870
13871+ int noscan;
13872+
13873 /**
13874 * mesh_rssi_threshold - Set mesh parameter mesh_rssi_threshold (dBm)
13875 *
13876diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
developer05f3b2b2024-08-19 19:17:34 +080013877index d245531cd..4777c3abe 100644
developer66e89bc2024-04-23 14:50:01 +080013878--- a/wpa_supplicant/ctrl_iface.c
13879+++ b/wpa_supplicant/ctrl_iface.c
13880@@ -2355,7 +2355,7 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
13881 pos += ret;
13882 }
13883
13884-#ifdef CONFIG_AP
13885+#if defined(CONFIG_AP) && defined(CONFIG_CTRL_IFACE_MIB)
13886 if (wpa_s->ap_iface) {
13887 pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
13888 end - pos,
developer05f3b2b2024-08-19 19:17:34 +080013889@@ -12561,6 +12561,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
developer66e89bc2024-04-23 14:50:01 +080013890 reply_len = -1;
13891 } else if (os_strncmp(buf, "NOTE ", 5) == 0) {
13892 wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
13893+#ifdef CONFIG_CTRL_IFACE_MIB
13894 } else if (os_strcmp(buf, "MIB") == 0) {
13895 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
13896 if (reply_len >= 0) {
developer05f3b2b2024-08-19 19:17:34 +080013897@@ -12573,6 +12574,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
developer66e89bc2024-04-23 14:50:01 +080013898 reply_size - reply_len);
13899 #endif /* CONFIG_MACSEC */
13900 }
13901+#endif
13902 } else if (os_strncmp(buf, "STATUS", 6) == 0) {
13903 reply_len = wpa_supplicant_ctrl_iface_status(
13904 wpa_s, buf + 6, reply, reply_size);
developer05f3b2b2024-08-19 19:17:34 +080013905@@ -13061,6 +13063,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
developer66e89bc2024-04-23 14:50:01 +080013906 reply_len = wpa_supplicant_ctrl_iface_bss(
13907 wpa_s, buf + 4, reply, reply_size);
13908 #ifdef CONFIG_AP
13909+#ifdef CONFIG_CTRL_IFACE_MIB
13910 } else if (os_strcmp(buf, "STA-FIRST") == 0) {
13911 reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
13912 } else if (os_strncmp(buf, "STA ", 4) == 0) {
developer05f3b2b2024-08-19 19:17:34 +080013913@@ -13069,12 +13072,15 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
developer66e89bc2024-04-23 14:50:01 +080013914 } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
13915 reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
13916 reply_size);
13917+#endif
13918+#ifdef CONFIG_CTRL_IFACE_MIB
13919 } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
13920 if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15))
13921 reply_len = -1;
13922 } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
13923 if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13))
13924 reply_len = -1;
13925+#endif
13926 } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
13927 if (ap_ctrl_iface_chanswitch(wpa_s, buf + 12))
13928 reply_len = -1;
developer05f3b2b2024-08-19 19:17:34 +080013929@@ -13233,7 +13239,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
developer66e89bc2024-04-23 14:50:01 +080013930 if (wpas_ctrl_iface_coloc_intf_report(wpa_s, buf + 18))
13931 reply_len = -1;
13932 #endif /* CONFIG_WNM */
13933-#ifdef CONFIG_WNM_AP
13934+#if defined(CONFIG_AP) && defined(CONFIG_WNM_AP)
13935 } else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
13936 if (ap_ctrl_iface_disassoc_imminent(wpa_s, buf + 18))
13937 reply_len = -1;
developer05f3b2b2024-08-19 19:17:34 +080013938@@ -13243,7 +13249,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
developer66e89bc2024-04-23 14:50:01 +080013939 } else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) {
13940 if (ap_ctrl_iface_bss_tm_req(wpa_s, buf + 11))
13941 reply_len = -1;
13942-#endif /* CONFIG_WNM_AP */
13943+#endif /* CONFIG_AP && CONFIG_WNM_AP */
13944 } else if (os_strcmp(buf, "FLUSH") == 0) {
13945 wpa_supplicant_ctrl_iface_flush(wpa_s);
13946 } else if (os_strncmp(buf, "RADIO_WORK ", 11) == 0) {
13947diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig
13948index 52befd8f1..ace6c5530 100644
13949--- a/wpa_supplicant/defconfig
13950+++ b/wpa_supplicant/defconfig
13951@@ -10,8 +10,8 @@
13952 # to override previous values of the variables.
13953
13954
13955-# Uncomment following two lines and fix the paths if you have installed OpenSSL
13956-# or GnuTLS in non-default location
13957+# Uncomment following two lines and fix the paths if you have installed TLS
13958+# libraries in a non-default location
13959 #CFLAGS += -I/usr/local/openssl/include
13960 #LIBS += -L/usr/local/openssl/lib
13961
13962@@ -20,6 +20,7 @@
13963 # used to fix build issues on such systems (krb5.h not found).
13964 #CFLAGS += -I/usr/include/kerberos
13965
13966+
13967 # Driver interface for generic Linux wireless extensions
13968 # Note: WEXT is deprecated in the current Linux kernel version and no new
13969 # functionality is added to it. nl80211-based interface is the new
13970@@ -329,6 +330,7 @@ CONFIG_BACKEND=file
13971 # openssl = OpenSSL (default)
13972 # gnutls = GnuTLS
13973 # internal = Internal TLSv1 implementation (experimental)
13974+# mbedtls = mbed TLS
13975 # linux = Linux kernel AF_ALG and internal TLSv1 implementation (experimental)
13976 # none = Empty template
13977 #CONFIG_TLS=openssl
13978diff --git a/wpa_supplicant/eapol_test.c b/wpa_supplicant/eapol_test.c
developer05f3b2b2024-08-19 19:17:34 +080013979index 0c17aaea4..3d35757bf 100644
developer66e89bc2024-04-23 14:50:01 +080013980--- a/wpa_supplicant/eapol_test.c
13981+++ b/wpa_supplicant/eapol_test.c
13982@@ -31,7 +31,12 @@
13983 #include "ctrl_iface.h"
13984 #include "pcsc_funcs.h"
13985 #include "wpas_glue.h"
13986+#include "drivers/driver.h"
13987
13988+void (*wpa_supplicant_event)(void *ctx, enum wpa_event_type event,
13989+ union wpa_event_data *data);
13990+void (*wpa_supplicant_event_global)(void *ctx, enum wpa_event_type event,
13991+ union wpa_event_data *data);
13992
13993 const struct wpa_driver_ops *const wpa_drivers[] = { NULL };
13994
developer05f3b2b2024-08-19 19:17:34 +080013995@@ -1328,6 +1333,10 @@ static void usage(void)
developer66e89bc2024-04-23 14:50:01 +080013996 "option several times.\n");
13997 }
13998
13999+extern void supplicant_event(void *ctx, enum wpa_event_type event,
14000+ union wpa_event_data *data);
14001+extern void supplicant_event_global(void *ctx, enum wpa_event_type event,
14002+ union wpa_event_data *data);
14003
14004 int main(int argc, char *argv[])
14005 {
developer05f3b2b2024-08-19 19:17:34 +080014006@@ -1351,6 +1360,8 @@ int main(int argc, char *argv[])
developer66e89bc2024-04-23 14:50:01 +080014007 if (os_program_init())
14008 return -1;
14009
14010+ wpa_supplicant_event = supplicant_event;
14011+ wpa_supplicant_event_global = supplicant_event_global;
14012 hostapd_logger_register_cb(hostapd_logger_cb);
14013
14014 os_memset(&eapol_test, 0, sizeof(eapol_test));
14015diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
developer05f3b2b2024-08-19 19:17:34 +080014016index bb0e95ba4..5c08d4a19 100644
developer66e89bc2024-04-23 14:50:01 +080014017--- a/wpa_supplicant/events.c
14018+++ b/wpa_supplicant/events.c
developer05f3b2b2024-08-19 19:17:34 +080014019@@ -6038,8 +6038,8 @@ static void wpas_link_reconfig(struct wpa_supplicant *wpa_s)
developer66e89bc2024-04-23 14:50:01 +080014020 }
14021
14022
14023-void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
14024- union wpa_event_data *data)
14025+void supplicant_event(void *ctx, enum wpa_event_type event,
14026+ union wpa_event_data *data)
14027 {
14028 struct wpa_supplicant *wpa_s = ctx;
14029 int resched;
developer05f3b2b2024-08-19 19:17:34 +080014030@@ -6074,6 +6074,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
developer66e89bc2024-04-23 14:50:01 +080014031 event_to_string(event), event);
14032 #endif /* CONFIG_NO_STDOUT_DEBUG */
14033
14034+ wpas_ucode_event(wpa_s, event, data);
14035 switch (event) {
14036 case EVENT_AUTH:
14037 #ifdef CONFIG_FST
developer05f3b2b2024-08-19 19:17:34 +080014038@@ -6991,7 +6992,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
developer66e89bc2024-04-23 14:50:01 +080014039 }
14040
14041
14042-void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
14043+void supplicant_event_global(void *ctx, enum wpa_event_type event,
14044 union wpa_event_data *data)
14045 {
14046 struct wpa_supplicant *wpa_s;
14047diff --git a/wpa_supplicant/main.c b/wpa_supplicant/main.c
14048index 9229eb51f..ee152c5b9 100644
14049--- a/wpa_supplicant/main.c
14050+++ b/wpa_supplicant/main.c
14051@@ -12,6 +12,7 @@
14052 #endif /* __linux__ */
14053
14054 #include "common.h"
14055+#include "build_features.h"
14056 #include "crypto/crypto.h"
14057 #include "fst/fst.h"
14058 #include "wpa_supplicant_i.h"
14059@@ -202,7 +203,7 @@ int main(int argc, char *argv[])
14060
14061 for (;;) {
14062 c = getopt(argc, argv,
14063- "b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuvW");
14064+ "b:Bc:C:D:de:f:g:G:hi:I:KLMm:nNo:O:p:P:qsTtuv::W");
14065 if (c < 0)
14066 break;
14067 switch (c) {
14068@@ -267,6 +268,9 @@ int main(int argc, char *argv[])
14069 params.conf_p2p_dev = optarg;
14070 break;
14071 #endif /* CONFIG_P2P */
14072+ case 'n':
14073+ iface_count = 0;
14074+ break;
14075 case 'o':
14076 params.override_driver = optarg;
14077 break;
14078@@ -302,8 +306,12 @@ int main(int argc, char *argv[])
14079 break;
14080 #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
14081 case 'v':
14082- printf("%s\n", wpa_supplicant_version);
14083- exitcode = 0;
14084+ if (optarg) {
14085+ exitcode = !has_feature(optarg);
14086+ } else {
14087+ printf("%s\n", wpa_supplicant_version);
14088+ exitcode = 0;
14089+ }
14090 goto out;
14091 case 'W':
14092 params.wait_for_monitor++;
14093diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c
14094index 85c1ea8ba..dabbb0334 100644
14095--- a/wpa_supplicant/mesh.c
14096+++ b/wpa_supplicant/mesh.c
14097@@ -506,6 +506,8 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
14098 frequency);
14099 goto out_free;
14100 }
14101+ if (conf->noscan)
14102+ ssid->noscan = 1;
14103
14104 if (ssid->mesh_basic_rates == NULL) {
14105 /*
14106@@ -630,6 +632,7 @@ int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s,
14107
14108 params->meshid = ssid->ssid;
14109 params->meshid_len = ssid->ssid_len;
14110+ params->mcast_rate = ssid->mcast_rate;
14111 ibss_mesh_setup_freq(wpa_s, ssid, &params->freq);
14112 wpa_s->mesh_ht_enabled = !!params->freq.ht_enabled;
14113 wpa_s->mesh_vht_enabled = !!params->freq.vht_enabled;
14114diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
developer05f3b2b2024-08-19 19:17:34 +080014115index af00e7910..b239410e8 100644
developer66e89bc2024-04-23 14:50:01 +080014116--- a/wpa_supplicant/wpa_cli.c
14117+++ b/wpa_supplicant/wpa_cli.c
14118@@ -26,6 +26,15 @@
14119 #include <cutils/properties.h>
14120 #endif /* ANDROID */
14121
14122+#ifndef CONFIG_P2P
14123+#define CONFIG_P2P
14124+#endif
14125+#ifndef CONFIG_AP
14126+#define CONFIG_AP
14127+#endif
14128+#ifndef CONFIG_MESH
14129+#define CONFIG_MESH
14130+#endif
14131
14132 static const char *const wpa_cli_version =
14133 "wpa_cli v" VERSION_STR "\n"
14134diff --git a/wpa_supplicant/wpa_priv.c b/wpa_supplicant/wpa_priv.c
14135index 88f3f2a52..92efe5629 100644
14136--- a/wpa_supplicant/wpa_priv.c
14137+++ b/wpa_supplicant/wpa_priv.c
14138@@ -1042,8 +1042,8 @@ static void wpa_priv_send_ft_response(struct wpa_priv_interface *iface,
14139 }
14140
14141
14142-void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
14143- union wpa_event_data *data)
14144+static void supplicant_event(void *ctx, enum wpa_event_type event,
14145+ union wpa_event_data *data)
14146 {
14147 struct wpa_priv_interface *iface = ctx;
14148
14149@@ -1106,7 +1106,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
14150 }
14151
14152
14153-void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
14154+void supplicant_event_global(void *ctx, enum wpa_event_type event,
14155 union wpa_event_data *data)
14156 {
14157 struct wpa_priv_global *global = ctx;
14158@@ -1220,6 +1220,8 @@ int main(int argc, char *argv[])
14159 if (os_program_init())
14160 return -1;
14161
14162+ wpa_supplicant_event = supplicant_event;
14163+ wpa_supplicant_event_global = supplicant_event_global;
14164 wpa_priv_fd_workaround();
14165
14166 os_memset(&global, 0, sizeof(global));
14167diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
developer05f3b2b2024-08-19 19:17:34 +080014168index 1e77493ef..32b178560 100644
developer66e89bc2024-04-23 14:50:01 +080014169--- a/wpa_supplicant/wpa_supplicant.c
14170+++ b/wpa_supplicant/wpa_supplicant.c
developer05f3b2b2024-08-19 19:17:34 +080014171@@ -1151,6 +1151,7 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
developer66e89bc2024-04-23 14:50:01 +080014172 sme_sched_obss_scan(wpa_s, 0);
14173 }
14174 wpa_s->wpa_state = state;
14175+ wpas_ucode_update_state(wpa_s);
14176
14177 #ifdef CONFIG_BGSCAN
14178 if (state == WPA_COMPLETED && wpa_s->current_ssid != wpa_s->bgscan_ssid)
developer05f3b2b2024-08-19 19:17:34 +080014179@@ -2831,7 +2832,7 @@ static int drv_supports_vht(struct wpa_supplicant *wpa_s,
developer66e89bc2024-04-23 14:50:01 +080014180 }
14181
14182
14183-static bool ibss_mesh_is_80mhz_avail(int channel, struct hostapd_hw_modes *mode)
14184+static bool ibss_mesh_is_80mhz_avail(int channel, struct hostapd_hw_modes *mode, bool dfs_enabled)
14185 {
14186 int i;
14187
developer05f3b2b2024-08-19 19:17:34 +080014188@@ -2840,7 +2841,10 @@ static bool ibss_mesh_is_80mhz_avail(int channel, struct hostapd_hw_modes *mode)
developer66e89bc2024-04-23 14:50:01 +080014189
14190 chan = hw_get_channel_chan(mode, i, NULL);
14191 if (!chan ||
14192- chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
14193+ chan->flag & HOSTAPD_CHAN_DISABLED)
14194+ return false;
14195+
14196+ if (!dfs_enabled && chan->flag & (HOSTAPD_CHAN_RADAR | HOSTAPD_CHAN_NO_IR))
14197 return false;
14198 }
14199
developer05f3b2b2024-08-19 19:17:34 +080014200@@ -2900,7 +2904,7 @@ static bool ibss_mesh_can_use_vht(struct wpa_supplicant *wpa_s,
developer66e89bc2024-04-23 14:50:01 +080014201 const struct wpa_ssid *ssid,
14202 struct hostapd_hw_modes *mode)
14203 {
14204- if (mode->mode != HOSTAPD_MODE_IEEE80211A)
14205+ if (mode->mode != HOSTAPD_MODE_IEEE80211A && !(ssid->noscan))
14206 return false;
14207
14208 if (!drv_supports_vht(wpa_s, ssid))
developer05f3b2b2024-08-19 19:17:34 +080014209@@ -2967,13 +2971,13 @@ static void ibss_mesh_select_40mhz(struct wpa_supplicant *wpa_s,
developer66e89bc2024-04-23 14:50:01 +080014210 const struct wpa_ssid *ssid,
14211 struct hostapd_hw_modes *mode,
14212 struct hostapd_freq_params *freq,
14213- int obss_scan) {
14214+ int obss_scan, bool dfs_enabled) {
14215 int chan_idx;
14216 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
14217 int i, res;
14218 unsigned int j;
14219 static const int ht40plus[] = {
developer05f3b2b2024-08-19 19:17:34 +080014220- 36, 44, 52, 60, 100, 108, 116, 124, 132, 140,
14221+ 1, 2, 3, 4, 5, 6, 7, 36, 44, 52, 60, 100, 108, 116, 124, 132, 140,
developer66e89bc2024-04-23 14:50:01 +080014222 149, 157, 165, 173, 184, 192
14223 };
developer05f3b2b2024-08-19 19:17:34 +080014224 int ht40 = -1;
14225@@ -2991,8 +2995,11 @@ static void ibss_mesh_select_40mhz(struct wpa_supplicant *wpa_s,
developer66e89bc2024-04-23 14:50:01 +080014226 return;
14227
14228 /* Check primary channel flags */
14229- if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
14230+ if (pri_chan->flag & HOSTAPD_CHAN_DISABLED)
14231 return;
14232+ if (pri_chan->flag & (HOSTAPD_CHAN_RADAR | HOSTAPD_CHAN_NO_IR))
14233+ if (!dfs_enabled)
14234+ return;
14235
14236 #ifdef CONFIG_HT_OVERRIDES
14237 if (ssid->disable_ht40)
developer05f3b2b2024-08-19 19:17:34 +080014238@@ -3018,8 +3025,11 @@ static void ibss_mesh_select_40mhz(struct wpa_supplicant *wpa_s,
developer66e89bc2024-04-23 14:50:01 +080014239 return;
14240
14241 /* Check secondary channel flags */
14242- if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
14243+ if (sec_chan->flag & HOSTAPD_CHAN_DISABLED)
14244 return;
14245+ if (sec_chan->flag & (HOSTAPD_CHAN_RADAR | HOSTAPD_CHAN_NO_IR))
14246+ if (!dfs_enabled)
14247+ return;
14248
14249 if (ht40 == -1) {
14250 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
developer05f3b2b2024-08-19 19:17:34 +080014251@@ -3074,7 +3084,7 @@ static bool ibss_mesh_select_80_160mhz(struct wpa_supplicant *wpa_s,
developer66e89bc2024-04-23 14:50:01 +080014252 const struct wpa_ssid *ssid,
14253 struct hostapd_hw_modes *mode,
14254 struct hostapd_freq_params *freq,
14255- int ieee80211_mode, bool is_6ghz) {
14256+ int ieee80211_mode, bool is_6ghz, bool dfs_enabled) {
14257 static const int bw80[] = {
14258 5180, 5260, 5500, 5580, 5660, 5745, 5825,
14259 5955, 6035, 6115, 6195, 6275, 6355, 6435,
developer05f3b2b2024-08-19 19:17:34 +080014260@@ -3119,7 +3129,7 @@ static bool ibss_mesh_select_80_160mhz(struct wpa_supplicant *wpa_s,
developer66e89bc2024-04-23 14:50:01 +080014261 goto skip_80mhz;
14262
14263 /* Use 40 MHz if channel not usable */
14264- if (!ibss_mesh_is_80mhz_avail(channel, mode))
14265+ if (!ibss_mesh_is_80mhz_avail(channel, mode, dfs_enabled))
14266 goto skip_80mhz;
14267
14268 chwidth = CONF_OPER_CHWIDTH_80MHZ;
developer05f3b2b2024-08-19 19:17:34 +080014269@@ -3133,7 +3143,7 @@ static bool ibss_mesh_select_80_160mhz(struct wpa_supplicant *wpa_s,
developer66e89bc2024-04-23 14:50:01 +080014270 if ((mode->he_capab[ieee80211_mode].phy_cap[
14271 HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
14272 HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G) && is_6ghz &&
14273- ibss_mesh_is_80mhz_avail(channel + 16, mode)) {
14274+ ibss_mesh_is_80mhz_avail(channel + 16, mode, dfs_enabled)) {
14275 for (j = 0; j < ARRAY_SIZE(bw160); j++) {
14276 if (freq->freq == bw160[j]) {
14277 chwidth = CONF_OPER_CHWIDTH_160MHZ;
developer05f3b2b2024-08-19 19:17:34 +080014278@@ -3161,10 +3171,12 @@ static bool ibss_mesh_select_80_160mhz(struct wpa_supplicant *wpa_s,
developer66e89bc2024-04-23 14:50:01 +080014279 if (!chan)
14280 continue;
14281
14282- if (chan->flag & (HOSTAPD_CHAN_DISABLED |
14283- HOSTAPD_CHAN_NO_IR |
14284- HOSTAPD_CHAN_RADAR))
14285+ if (chan->flag & HOSTAPD_CHAN_DISABLED)
14286 continue;
14287+ if (chan->flag & (HOSTAPD_CHAN_RADAR |
14288+ HOSTAPD_CHAN_NO_IR))
14289+ if (!dfs_enabled)
14290+ continue;
14291
14292 /* Found a suitable second segment for 80+80 */
14293 chwidth = CONF_OPER_CHWIDTH_80P80MHZ;
developer05f3b2b2024-08-19 19:17:34 +080014294@@ -3216,12 +3228,17 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
developer66e89bc2024-04-23 14:50:01 +080014295 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
14296 enum hostapd_hw_mode hw_mode;
14297 struct hostapd_hw_modes *mode = NULL;
developer05f3b2b2024-08-19 19:17:34 +080014298- int obss_scan = 1;
14299+ int obss_scan = !(ssid->noscan);
developer66e89bc2024-04-23 14:50:01 +080014300 u8 channel;
14301 bool is_6ghz, is_24ghz;
14302+ bool dfs_enabled = wpa_s->conf->country[0] && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_RADAR);
14303
14304 freq->freq = ssid->frequency;
14305
14306+ if (ssid->fixed_freq) {
14307+ obss_scan = 0;
14308+ }
14309+
14310 if (ssid->mode == WPAS_MODE_IBSS && !ssid->fixed_freq) {
14311 struct wpa_bss *bss = ibss_find_existing_bss(wpa_s, ssid);
14312
developer05f3b2b2024-08-19 19:17:34 +080014313@@ -3259,11 +3276,13 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
developer66e89bc2024-04-23 14:50:01 +080014314 freq->he_enabled = ibss_mesh_can_use_he(wpa_s, ssid, mode,
14315 ieee80211_mode);
14316 freq->channel = channel;
14317+ if (mode->mode == HOSTAPD_MODE_IEEE80211G && ssid->noscan)
14318+ ibss_mesh_select_40mhz(wpa_s, ssid, mode, freq, obss_scan, dfs_enabled);
14319 /* Setup higher BW only for 5 GHz */
14320 if (mode->mode == HOSTAPD_MODE_IEEE80211A) {
14321- ibss_mesh_select_40mhz(wpa_s, ssid, mode, freq, obss_scan);
14322+ ibss_mesh_select_40mhz(wpa_s, ssid, mode, freq, obss_scan, dfs_enabled);
14323 if (!ibss_mesh_select_80_160mhz(wpa_s, ssid, mode, freq,
14324- ieee80211_mode, is_6ghz))
14325+ ieee80211_mode, is_6ghz, dfs_enabled))
14326 freq->he_enabled = freq->vht_enabled = false;
14327 }
14328
developer05f3b2b2024-08-19 19:17:34 +080014329@@ -4449,6 +4468,12 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
developer66e89bc2024-04-23 14:50:01 +080014330 params.beacon_int = ssid->beacon_int;
14331 else
14332 params.beacon_int = wpa_s->conf->beacon_int;
14333+ int i = 0;
14334+ while (i < WLAN_SUPP_RATES_MAX) {
14335+ params.rates[i] = ssid->rates[i];
14336+ i++;
14337+ }
14338+ params.mcast_rate = ssid->mcast_rate;
14339 }
14340
14341 if (bss && ssid->enable_edmg)
developer05f3b2b2024-08-19 19:17:34 +080014342@@ -6093,7 +6118,7 @@ wpa_supplicant_alloc(struct wpa_supplicant *parent)
developer66e89bc2024-04-23 14:50:01 +080014343 if (wpa_s == NULL)
14344 return NULL;
14345 wpa_s->scan_req = INITIAL_SCAN_REQ;
14346- wpa_s->scan_interval = 5;
14347+ wpa_s->scan_interval = 1;
14348 wpa_s->new_connection = 1;
14349 wpa_s->parent = parent ? parent : wpa_s;
14350 wpa_s->p2pdev = wpa_s->parent;
developer05f3b2b2024-08-19 19:17:34 +080014351@@ -7809,7 +7834,6 @@ struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
developer66e89bc2024-04-23 14:50:01 +080014352 return NULL;
14353 }
14354
14355-
14356 /**
14357 * wpa_supplicant_match_existing - Match existing interfaces
14358 * @global: Pointer to global data from wpa_supplicant_init()
developer05f3b2b2024-08-19 19:17:34 +080014359@@ -7844,6 +7868,11 @@ static int wpa_supplicant_match_existing(struct wpa_global *global)
developer66e89bc2024-04-23 14:50:01 +080014360
14361 #endif /* CONFIG_MATCH_IFACE */
14362
14363+extern void supplicant_event(void *ctx, enum wpa_event_type event,
14364+ union wpa_event_data *data);
14365+
14366+extern void supplicant_event_global(void *ctx, enum wpa_event_type event,
14367+ union wpa_event_data *data);
14368
14369 /**
14370 * wpa_supplicant_add_iface - Add a new network interface
developer05f3b2b2024-08-19 19:17:34 +080014371@@ -7926,6 +7955,9 @@ struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
developer66e89bc2024-04-23 14:50:01 +080014372 }
14373 #endif /* CONFIG_P2P */
14374
14375+ wpas_ubus_add_bss(wpa_s);
14376+ wpas_ucode_add_bss(wpa_s);
14377+
14378 return wpa_s;
14379 }
14380
developer05f3b2b2024-08-19 19:17:34 +080014381@@ -7952,6 +7984,9 @@ int wpa_supplicant_remove_iface(struct wpa_global *global,
developer66e89bc2024-04-23 14:50:01 +080014382 struct wpa_supplicant *parent = wpa_s->parent;
14383 #endif /* CONFIG_MESH */
14384
14385+ wpas_ucode_free_bss(wpa_s);
14386+ wpas_ubus_free_bss(wpa_s);
14387+
14388 /* Remove interface from the global list of interfaces */
14389 prev = global->ifaces;
14390 if (prev == wpa_s) {
developer05f3b2b2024-08-19 19:17:34 +080014391@@ -8100,6 +8135,8 @@ struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
developer66e89bc2024-04-23 14:50:01 +080014392 #ifndef CONFIG_NO_WPA_MSG
14393 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
14394 #endif /* CONFIG_NO_WPA_MSG */
14395+ wpa_supplicant_event = supplicant_event;
14396+ wpa_supplicant_event_global = supplicant_event_global;
14397
14398 if (params->wpa_debug_file_path)
14399 wpa_debug_open_file(params->wpa_debug_file_path);
developer05f3b2b2024-08-19 19:17:34 +080014400@@ -8258,6 +8295,7 @@ struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
developer66e89bc2024-04-23 14:50:01 +080014401
14402 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
14403 wpas_periodic, global, NULL);
14404+ wpas_ucode_init(global);
14405
14406 return global;
14407 }
developer05f3b2b2024-08-19 19:17:34 +080014408@@ -8330,6 +8368,8 @@ void wpa_supplicant_deinit(struct wpa_global *global)
developer66e89bc2024-04-23 14:50:01 +080014409
14410 wpas_notify_supplicant_deinitialized(global);
14411
14412+ wpas_ucode_free();
14413+
14414 eap_peer_unregister_methods();
14415 #ifdef CONFIG_AP
14416 eap_server_unregister_methods();
14417diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
developer05f3b2b2024-08-19 19:17:34 +080014418index 48ec95fa5..952a3bd5a 100644
developer66e89bc2024-04-23 14:50:01 +080014419--- a/wpa_supplicant/wpa_supplicant_i.h
14420+++ b/wpa_supplicant/wpa_supplicant_i.h
14421@@ -21,6 +21,8 @@
14422 #include "config_ssid.h"
14423 #include "wmm_ac.h"
14424 #include "pasn/pasn_common.h"
14425+#include "ubus.h"
14426+#include "ucode.h"
14427
14428 extern const char *const wpa_supplicant_version;
14429 extern const char *const wpa_supplicant_license;
14430@@ -319,6 +321,8 @@ struct wpa_global {
14431 #endif /* CONFIG_WIFI_DISPLAY */
14432
14433 struct psk_list_entry *add_psk; /* From group formation */
14434+
14435+ struct ubus_object ubus_global;
14436 };
14437
14438
14439@@ -693,6 +697,8 @@ struct wpa_supplicant {
14440 unsigned char own_addr[ETH_ALEN];
14441 unsigned char perm_addr[ETH_ALEN];
14442 char ifname[100];
14443+ struct wpas_ubus_bss ubus;
14444+ struct wpas_ucode_bss ucode;
14445 #ifdef CONFIG_MATCH_IFACE
14446 int matched;
14447 #endif /* CONFIG_MATCH_IFACE */
14448diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c
developer05f3b2b2024-08-19 19:17:34 +080014449index 7b9cf7f9e..03748f4bb 100644
developer66e89bc2024-04-23 14:50:01 +080014450--- a/wpa_supplicant/wps_supplicant.c
14451+++ b/wpa_supplicant/wps_supplicant.c
14452@@ -33,6 +33,7 @@
14453 #include "p2p/p2p.h"
14454 #include "p2p_supplicant.h"
14455 #include "wps_supplicant.h"
14456+#include "ubus.h"
14457
14458
14459 #ifndef WPS_PIN_SCAN_IGNORE_SEL_REG
14460@@ -401,6 +402,8 @@ static int wpa_supplicant_wps_cred(void *ctx,
14461 wpa_hexdump_key(MSG_DEBUG, "WPS: Received Credential attribute",
14462 cred->cred_attr, cred->cred_attr_len);
14463
14464+ wpas_ubus_notify(wpa_s, cred);
14465+
14466 if (wpa_s->conf->wps_cred_processing == 1)
14467 return 0;
14468
14469diff --git a/wpa_supplicant/wps_supplicant.h b/wpa_supplicant/wps_supplicant.h
14470index aae3f7cb5..30b4e9105 100644
14471--- a/wpa_supplicant/wps_supplicant.h
14472+++ b/wpa_supplicant/wps_supplicant.h
14473@@ -9,6 +9,7 @@
14474 #ifndef WPS_SUPPLICANT_H
14475 #define WPS_SUPPLICANT_H
14476
14477+struct wpa_bss;
14478 struct wpa_scan_results;
14479
14480 #ifdef CONFIG_WPS
14481@@ -16,8 +17,6 @@ struct wpa_scan_results;
14482 #include "wps/wps.h"
14483 #include "wps/wps_defs.h"
14484
14485-struct wpa_bss;
14486-
14487 struct wps_new_ap_settings {
14488 const char *ssid_hex;
14489 const char *auth;
14490--
developer05f3b2b2024-08-19 19:17:34 +0800144912.18.0
developer66e89bc2024-04-23 14:50:01 +080014492