blob: 1dff1f33dc75d455ab5d1ff330ad0054d2e45541 [file] [log] [blame]
developer66e89bc2024-04-23 14:50:01 +08001From 2eff271199b22ce44432d531e8b44809368ac5d2 Mon Sep 17 00:00:00 2001
2From: Evelyn Tsai <evelyn.tsai@mediatek.com>
3Date: Tue, 23 Jan 2024 17:07:17 +0800
4Subject: [PATCH 028/104] hostapd: sync 2024-01-18 openwrt/trunk patch folder
5
6---
7 hostapd/Makefile | 149 +-
8 hostapd/config_file.c | 39 +-
9 hostapd/ctrl_iface.c | 4 +
10 hostapd/defconfig | 15 +-
11 hostapd/hostapd_cli.c | 10 +-
12 hostapd/main.c | 21 +-
13 src/ap/acs.c | 5 +-
14 src/ap/airtime_policy.c | 15 +-
15 src/ap/ap_config.h | 8 +
16 src/ap/ap_drv_ops.c | 5 +-
17 src/ap/ap_drv_ops.h | 21 +-
18 src/ap/beacon.c | 14 +-
19 src/ap/ctrl_iface_ap.c | 45 +-
20 src/ap/dfs.c | 22 +-
21 src/ap/drv_callbacks.c | 16 +-
22 src/ap/hostapd.c | 51 +-
23 src/ap/hostapd.h | 42 +
24 src/ap/hw_features.c | 3 +-
25 src/ap/ieee802_11.c | 50 +-
26 src/ap/ieee802_11_ht.c | 15 +
27 src/ap/ieee802_11_shared.c | 2 -
28 src/ap/ieee802_11_vht.c | 17 +
29 src/ap/ieee802_1x.c | 6 +
30 src/ap/ndisc_snoop.c | 1 +
31 src/ap/rrm.c | 8 +
32 src/ap/sta_info.c | 35 +-
33 src/ap/sta_info.h | 12 +-
34 src/ap/vlan_full.c | 4 +
35 src/ap/vlan_init.c | 8 +-
36 src/ap/wnm_ap.c | 16 +-
37 src/ap/wpa_auth.c | 3 +-
38 src/ap/wpa_auth_glue.c | 9 +-
39 src/ap/wps_hostapd.c | 6 +-
40 src/ap/x_snoop.c | 22 +-
41 src/common/dpp_crypto.c | 10 +-
42 src/common/hw_features_common.c | 1 +
43 src/common/ieee802_11_defs.h | 2 +
44 src/common/sae.c | 7 +
45 src/common/wpa_common.c | 40 +-
46 src/common/wpa_ctrl.c | 10 +-
47 src/crypto/Makefile | 129 +-
48 src/crypto/crypto_mbedtls.c | 4228 +++++++++++++++++++++
49 src/crypto/crypto_module_tests.c | 134 +
50 src/crypto/crypto_wolfssl.c | 18 +
51 src/crypto/tls_mbedtls.c | 3313 ++++++++++++++++
52 src/drivers/driver.h | 36 +-
53 src/drivers/driver_nl80211.c | 300 +-
54 src/drivers/driver_nl80211_capa.c | 4 +
55 src/drivers/driver_nl80211_event.c | 5 +
56 src/drivers/driver_nl80211_scan.c | 2 +-
57 src/drivers/drivers.c | 4 +
58 src/drivers/drivers.mak | 4 +-
59 src/drivers/rfkill.h | 16 +
60 src/radius/radius_client.c | 34 +
61 src/radius/radius_client.h | 2 +
62 src/radius/radius_das.c | 201 +-
63 src/radius/radius_das.h | 1 +
64 src/radius/radius_server.c | 61 +-
65 src/rsn_supp/wpa.c | 3 +
66 src/tls/Makefile | 11 +
67 src/utils/eloop.c | 20 +-
68 src/utils/eloop.h | 8 +
69 src/utils/uloop.c | 64 +
70 src/utils/wpa_debug.c | 49 +-
71 src/utils/wpa_debug.h | 73 +-
72 tests/Makefile | 65 +-
73 tests/hwsim/example-hostapd.config | 10 +-
74 tests/hwsim/example-wpa_supplicant.config | 11 +-
75 tests/hwsim/test_ap_eap.py | 112 +-
76 tests/hwsim/test_ap_ft.py | 4 +-
77 tests/hwsim/test_authsrv.py | 9 +-
78 tests/hwsim/test_dpp.py | 19 +-
79 tests/hwsim/test_erp.py | 16 +-
80 tests/hwsim/test_fils.py | 12 +
81 tests/hwsim/test_pmksa_cache.py | 4 +-
82 tests/hwsim/test_sae.py | 7 +
83 tests/hwsim/test_suite_b.py | 3 +
84 tests/hwsim/test_wpas_ctrl.py | 2 +-
85 tests/hwsim/utils.py | 8 +-
86 tests/test-crypto_module.c | 16 +
87 tests/test-https.c | 12 +-
88 tests/test-https_server.c | 12 +-
89 wpa_supplicant/Makefile | 144 +-
90 wpa_supplicant/ap.c | 22 +-
91 wpa_supplicant/config.c | 95 +
92 wpa_supplicant/config_file.c | 8 +-
93 wpa_supplicant/config_ssid.h | 7 +
94 wpa_supplicant/ctrl_iface.c | 12 +-
95 wpa_supplicant/defconfig | 6 +-
96 wpa_supplicant/eapol_test.c | 11 +
97 wpa_supplicant/events.c | 13 +-
98 wpa_supplicant/main.c | 14 +-
99 wpa_supplicant/mesh.c | 3 +
100 wpa_supplicant/wpa_cli.c | 9 +
101 wpa_supplicant/wpa_priv.c | 8 +-
102 wpa_supplicant/wpa_supplicant.c | 75 +-
103 wpa_supplicant/wpa_supplicant_i.h | 6 +
104 wpa_supplicant/wps_supplicant.c | 3 +
105 wpa_supplicant/wps_supplicant.h | 3 +-
106 99 files changed, 9786 insertions(+), 464 deletions(-)
107 create mode 100644 src/crypto/crypto_mbedtls.c
108 create mode 100644 src/crypto/tls_mbedtls.c
109 create mode 100644 src/utils/uloop.c
110 create mode 100644 tests/test-crypto_module.c
111
112diff --git a/hostapd/Makefile b/hostapd/Makefile
113index 405e05e5f..f5c1dc029 100644
114--- a/hostapd/Makefile
115+++ b/hostapd/Makefile
116@@ -1,6 +1,7 @@
117 ALL=hostapd hostapd_cli
118 CONFIG_FILE = .config
119
120+-include $(if $(MULTICALL), ../wpa_supplicant/.config)
121 include ../src/build.rules
122
123 ifdef LIBS
124@@ -62,6 +63,10 @@ endif
125 OBJS += main.o
126 OBJS += config_file.o
127
128+ifdef CONFIG_RADIUS_SERVER
129+OBJS += radius.o
130+endif
131+
132 OBJS += ../src/ap/hostapd.o
133 OBJS += ../src/ap/wpa_auth_glue.o
134 OBJS += ../src/ap/drv_callbacks.o
135@@ -171,6 +176,24 @@ OBJS += ../src/common/hw_features_common.o
136
137 OBJS += ../src/eapol_auth/eapol_auth_sm.o
138
139+ifdef CONFIG_UBUS
140+CFLAGS += -DUBUS_SUPPORT
141+OBJS += ../src/ap/ubus.o
142+LIBS += -lubus
143+NEED_ULOOP:=y
144+endif
145+
146+ifdef CONFIG_UCODE
147+CFLAGS += -DUCODE_SUPPORT
148+OBJS += ../src/utils/ucode.o
149+OBJS += ../src/ap/ucode.o
150+NEED_ULOOP:=y
151+endif
152+
153+ifdef NEED_ULOOP
154+OBJS += ../src/utils/uloop.o
155+LIBS += -lubox
156+endif
157
158 ifdef CONFIG_CODE_COVERAGE
159 CFLAGS += -O0 -fprofile-arcs -ftest-coverage -U_FORTIFY_SOURCE
160@@ -205,7 +228,8 @@ endif
161
162 ifdef CONFIG_NO_VLAN
163 CFLAGS += -DCONFIG_NO_VLAN
164-else
165+endif
166+ifneq ($(findstring CONFIG_NO_VLAN,$(CFLAGS)), CONFIG_NO_VLAN)
167 OBJS += ../src/ap/vlan_init.o
168 OBJS += ../src/ap/vlan_ifconfig.o
169 OBJS += ../src/ap/vlan.o
170@@ -225,6 +249,9 @@ endif
171 ifdef CONFIG_NO_CTRL_IFACE
172 CFLAGS += -DCONFIG_NO_CTRL_IFACE
173 else
174+ifdef CONFIG_CTRL_IFACE_MIB
175+CFLAGS += -DCONFIG_CTRL_IFACE_MIB
176+endif
177 ifeq ($(CONFIG_CTRL_IFACE), udp)
178 CFLAGS += -DCONFIG_CTRL_IFACE_UDP
179 else
180@@ -332,6 +359,7 @@ ifdef CONFIG_FILS
181 CFLAGS += -DCONFIG_FILS
182 OBJS += ../src/ap/fils_hlp.o
183 NEED_SHA384=y
184+NEED_HMAC_SHA384_KDF=y
185 NEED_AES_SIV=y
186 ifdef CONFIG_FILS_SK_PFS
187 CFLAGS += -DCONFIG_FILS_SK_PFS
188@@ -364,10 +392,14 @@ CFLAGS += -DCONFIG_MBO
189 OBJS += ../src/ap/mbo_ap.o
190 endif
191
192+ifndef MULTICALL
193+CFLAGS += -DNO_SUPPLICANT
194+endif
195+
196 include ../src/drivers/drivers.mak
197-OBJS += $(DRV_AP_OBJS)
198-CFLAGS += $(DRV_AP_CFLAGS)
199-LDFLAGS += $(DRV_AP_LDFLAGS)
200+OBJS += $(sort $(DRV_AP_OBJS) $(if $(MULTICALL),$(DRV_WPA_OBJS)))
201+CFLAGS += $(DRV_AP_CFLAGS) $(if $(MULTICALL),$(DRV_WPA_CFLAGS))
202+LDFLAGS += $(DRV_AP_LDFLAGS) $(if $(MULTICALL),$(DRV_WPA_LDFLAGS))
203 LIBS += $(DRV_AP_LIBS)
204
205 ifdef CONFIG_L2_PACKET
206@@ -714,6 +746,7 @@ CFLAGS += -DCONFIG_TLSV12
207 endif
208
209 ifeq ($(CONFIG_TLS), wolfssl)
210+CFLAGS += -DCONFIG_TLS_WOLFSSL
211 CONFIG_CRYPTO=wolfssl
212 ifdef TLS_FUNCS
213 OBJS += ../src/crypto/tls_wolfssl.o
214@@ -734,6 +767,7 @@ endif
215 endif
216
217 ifeq ($(CONFIG_TLS), openssl)
218+CFLAGS += -DCONFIG_TLS_OPENSSL
219 CFLAGS += -DCRYPTO_RSA_OAEP_SHA256
220 CONFIG_CRYPTO=openssl
221 ifdef TLS_FUNCS
222@@ -763,7 +797,39 @@ endif
223 CFLAGS += -DTLS_DEFAULT_CIPHERS=\"$(CONFIG_TLS_DEFAULT_CIPHERS)\"
224 endif
225
226+ifeq ($(CONFIG_TLS), mbedtls)
227+CFLAGS += -DCONFIG_TLS_MBEDTLS
228+ifndef CONFIG_CRYPTO
229+CONFIG_CRYPTO=mbedtls
230+endif
231+ifdef TLS_FUNCS
232+OBJS += ../src/crypto/tls_mbedtls.o
233+LIBS += -lmbedtls
234+ifndef CONFIG_DPP
235+LIBS += -lmbedx509
236+endif
237+endif
238+OBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o
239+HOBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o
240+SOBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o
241+ifeq ($(CONFIG_CRYPTO), mbedtls)
242+ifdef CONFIG_DPP
243+LIBS += -lmbedx509
244+LIBS_h += -lmbedx509
245+LIBS_n += -lmbedx509
246+LIBS_s += -lmbedx509
247+endif
248+LIBS += -lmbedcrypto
249+LIBS_h += -lmbedcrypto
250+LIBS_n += -lmbedcrypto
251+LIBS_s += -lmbedcrypto
252+# XXX: create a config option?
253+CFLAGS += -DCRYPTO_RSA_OAEP_SHA256
254+endif
255+endif
256+
257 ifeq ($(CONFIG_TLS), gnutls)
258+CFLAGS += -DCONFIG_TLS_GNUTLS
259 ifndef CONFIG_CRYPTO
260 # default to libgcrypt
261 CONFIG_CRYPTO=gnutls
262@@ -794,6 +860,7 @@ endif
263 endif
264
265 ifeq ($(CONFIG_TLS), internal)
266+CFLAGS += -DCONFIG_TLS_INTERNAL
267 ifndef CONFIG_CRYPTO
268 CONFIG_CRYPTO=internal
269 endif
270@@ -872,6 +939,7 @@ endif
271 endif
272
273 ifeq ($(CONFIG_TLS), linux)
274+CFLAGS += -DCONFIG_TLS_INTERNAL
275 OBJS += ../src/crypto/crypto_linux.o
276 ifdef TLS_FUNCS
277 OBJS += ../src/crypto/crypto_internal-rsa.o
278@@ -942,9 +1010,11 @@ endif
279
280 ifneq ($(CONFIG_TLS), openssl)
281 ifneq ($(CONFIG_TLS), wolfssl)
282+ifneq ($(CONFIG_TLS), mbedtls)
283 AESOBJS += ../src/crypto/aes-wrap.o
284 endif
285 endif
286+endif
287 ifdef NEED_AES_EAX
288 AESOBJS += ../src/crypto/aes-eax.o
289 NEED_AES_CTR=y
290@@ -954,38 +1024,48 @@ AESOBJS += ../src/crypto/aes-siv.o
291 NEED_AES_CTR=y
292 endif
293 ifdef NEED_AES_CTR
294+ifneq ($(CONFIG_TLS), mbedtls)
295 AESOBJS += ../src/crypto/aes-ctr.o
296 endif
297+endif
298 ifdef NEED_AES_ENCBLOCK
299+ifneq ($(CONFIG_TLS), mbedtls)
300 AESOBJS += ../src/crypto/aes-encblock.o
301 endif
302+endif
303 ifneq ($(CONFIG_TLS), openssl)
304 ifneq ($(CONFIG_TLS), linux)
305 ifneq ($(CONFIG_TLS), wolfssl)
306+ifneq ($(CONFIG_TLS), mbedtls)
307 AESOBJS += ../src/crypto/aes-omac1.o
308 endif
309 endif
310 endif
311+endif
312 ifdef NEED_AES_UNWRAP
313 ifneq ($(CONFIG_TLS), openssl)
314 ifneq ($(CONFIG_TLS), linux)
315 ifneq ($(CONFIG_TLS), wolfssl)
316+ifneq ($(CONFIG_TLS), mbedtls)
317 NEED_AES_DEC=y
318 AESOBJS += ../src/crypto/aes-unwrap.o
319 endif
320 endif
321 endif
322 endif
323+endif
324 ifdef NEED_AES_CBC
325 NEED_AES_DEC=y
326 ifneq ($(CONFIG_TLS), openssl)
327 ifneq ($(CONFIG_TLS), linux)
328 ifneq ($(CONFIG_TLS), wolfssl)
329+ifneq ($(CONFIG_TLS), mbedtls)
330 AESOBJS += ../src/crypto/aes-cbc.o
331 endif
332 endif
333 endif
334 endif
335+endif
336 ifdef NEED_AES_DEC
337 ifdef CONFIG_INTERNAL_AES
338 AESOBJS += ../src/crypto/aes-internal-dec.o
339@@ -1000,12 +1080,16 @@ ifneq ($(CONFIG_TLS), openssl)
340 ifneq ($(CONFIG_TLS), linux)
341 ifneq ($(CONFIG_TLS), gnutls)
342 ifneq ($(CONFIG_TLS), wolfssl)
343+ifneq ($(CONFIG_TLS), mbedtls)
344 SHA1OBJS += ../src/crypto/sha1.o
345 endif
346 endif
347 endif
348 endif
349+endif
350+ifneq ($(CONFIG_TLS), mbedtls)
351 SHA1OBJS += ../src/crypto/sha1-prf.o
352+endif
353 ifdef CONFIG_INTERNAL_SHA1
354 SHA1OBJS += ../src/crypto/sha1-internal.o
355 ifdef NEED_FIPS186_2_PRF
356@@ -1014,16 +1098,22 @@ endif
357 endif
358 ifneq ($(CONFIG_TLS), openssl)
359 ifneq ($(CONFIG_TLS), wolfssl)
360+ifneq ($(CONFIG_TLS), mbedtls)
361 SHA1OBJS += ../src/crypto/sha1-pbkdf2.o
362 endif
363 endif
364+endif
365 ifdef NEED_T_PRF
366+ifneq ($(CONFIG_TLS), mbedtls)
367 SHA1OBJS += ../src/crypto/sha1-tprf.o
368 endif
369+endif
370 ifdef NEED_TLS_PRF
371+ifneq ($(CONFIG_TLS), mbedtls)
372 SHA1OBJS += ../src/crypto/sha1-tlsprf.o
373 endif
374 endif
375+endif
376
377 ifdef NEED_SHA1
378 OBJS += $(SHA1OBJS)
379@@ -1033,11 +1123,13 @@ ifneq ($(CONFIG_TLS), openssl)
380 ifneq ($(CONFIG_TLS), linux)
381 ifneq ($(CONFIG_TLS), gnutls)
382 ifneq ($(CONFIG_TLS), wolfssl)
383+ifneq ($(CONFIG_TLS), mbedtls)
384 OBJS += ../src/crypto/md5.o
385 endif
386 endif
387 endif
388 endif
389+endif
390
391 ifdef NEED_MD5
392 ifdef CONFIG_INTERNAL_MD5
393@@ -1076,56 +1168,81 @@ ifneq ($(CONFIG_TLS), openssl)
394 ifneq ($(CONFIG_TLS), linux)
395 ifneq ($(CONFIG_TLS), gnutls)
396 ifneq ($(CONFIG_TLS), wolfssl)
397+ifneq ($(CONFIG_TLS), mbedtls)
398 OBJS += ../src/crypto/sha256.o
399 endif
400 endif
401 endif
402 endif
403+endif
404+ifneq ($(CONFIG_TLS), mbedtls)
405 OBJS += ../src/crypto/sha256-prf.o
406+endif
407 ifdef CONFIG_INTERNAL_SHA256
408 OBJS += ../src/crypto/sha256-internal.o
409 endif
410 ifdef NEED_TLS_PRF_SHA256
411+ifneq ($(CONFIG_TLS), mbedtls)
412 OBJS += ../src/crypto/sha256-tlsprf.o
413 endif
414+endif
415 ifdef NEED_TLS_PRF_SHA384
416+ifneq ($(CONFIG_TLS), mbedtls)
417 OBJS += ../src/crypto/sha384-tlsprf.o
418 endif
419+endif
420 ifdef NEED_HMAC_SHA256_KDF
421+CFLAGS += -DCONFIG_HMAC_SHA256_KDF
422+ifneq ($(CONFIG_TLS), mbedtls)
423 OBJS += ../src/crypto/sha256-kdf.o
424 endif
425+endif
426 ifdef NEED_HMAC_SHA384_KDF
427+CFLAGS += -DCONFIG_HMAC_SHA384_KDF
428+ifneq ($(CONFIG_TLS), mbedtls)
429 OBJS += ../src/crypto/sha384-kdf.o
430 endif
431+endif
432 ifdef NEED_HMAC_SHA512_KDF
433+CFLAGS += -DCONFIG_HMAC_SHA512_KDF
434+ifneq ($(CONFIG_TLS), mbedtls)
435 OBJS += ../src/crypto/sha512-kdf.o
436 endif
437+endif
438 ifdef NEED_SHA384
439 CFLAGS += -DCONFIG_SHA384
440 ifneq ($(CONFIG_TLS), openssl)
441 ifneq ($(CONFIG_TLS), linux)
442 ifneq ($(CONFIG_TLS), gnutls)
443 ifneq ($(CONFIG_TLS), wolfssl)
444+ifneq ($(CONFIG_TLS), mbedtls)
445 OBJS += ../src/crypto/sha384.o
446 endif
447 endif
448 endif
449 endif
450+endif
451+ifneq ($(CONFIG_TLS), mbedtls)
452 OBJS += ../src/crypto/sha384-prf.o
453 endif
454+endif
455 ifdef NEED_SHA512
456 CFLAGS += -DCONFIG_SHA512
457 ifneq ($(CONFIG_TLS), openssl)
458 ifneq ($(CONFIG_TLS), linux)
459 ifneq ($(CONFIG_TLS), gnutls)
460 ifneq ($(CONFIG_TLS), wolfssl)
461+ifneq ($(CONFIG_TLS), mbedtls)
462 OBJS += ../src/crypto/sha512.o
463 endif
464 endif
465 endif
466 endif
467+endif
468+ifneq ($(CONFIG_TLS), mbedtls)
469 OBJS += ../src/crypto/sha512-prf.o
470 endif
471+endif
472
473 ifdef CONFIG_INTERNAL_SHA384
474 CFLAGS += -DCONFIG_INTERNAL_SHA384
475@@ -1170,11 +1287,13 @@ HOBJS += $(SHA1OBJS)
476 ifneq ($(CONFIG_TLS), openssl)
477 ifneq ($(CONFIG_TLS), linux)
478 ifneq ($(CONFIG_TLS), wolfssl)
479+ifneq ($(CONFIG_TLS), mbedtls)
480 HOBJS += ../src/crypto/md5.o
481 endif
482 endif
483 endif
484 endif
485+endif
486
487 ifdef CONFIG_RADIUS_SERVER
488 CFLAGS += -DRADIUS_SERVER
489@@ -1311,8 +1430,14 @@ install: $(addprefix $(DESTDIR)$(BINDIR)/,$(ALL))
490 _OBJS_VAR := OBJS
491 include ../src/objs.mk
492
493+hostapd_multi.a: $(BCHECK) $(OBJS)
494+ $(Q)$(CC) -c -o hostapd_multi.o -Dmain=hostapd_main $(CFLAGS) main.c
495+ @$(E) " CC " $<
496+ @rm -f $@
497+ @$(AR) cr $@ hostapd_multi.o $(OBJS)
498+
499 hostapd: $(OBJS)
500- $(Q)$(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS)
501+ +$(Q)$(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS)
502 @$(E) " LD " $@
503
504 ifdef CONFIG_WPA_TRACE
505@@ -1323,7 +1448,7 @@ _OBJS_VAR := OBJS_c
506 include ../src/objs.mk
507
508 hostapd_cli: $(OBJS_c)
509- $(Q)$(CC) $(LDFLAGS) -o hostapd_cli $(OBJS_c) $(LIBS_c)
510+ +$(Q)$(CC) $(LDFLAGS) -o hostapd_cli $(OBJS_c) $(LIBS_c)
511 @$(E) " LD " $@
512
513 NOBJS = nt_password_hash.o ../src/crypto/ms_funcs.o $(SHA1OBJS)
514@@ -1347,7 +1472,9 @@ NOBJS += ../src/utils/trace.o
515 endif
516
517 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
518+ifneq ($(CONFIG_TLS), mbedtls)
519 HOBJS += ../src/crypto/aes-encblock.o
520+endif
521 ifdef CONFIG_INTERNAL_AES
522 HOBJS += ../src/crypto/aes-internal.o
523 HOBJS += ../src/crypto/aes-internal-enc.o
524@@ -1370,13 +1497,17 @@ SOBJS += ../src/common/sae.o
525 SOBJS += ../src/common/sae_pk.o
526 SOBJS += ../src/common/dragonfly.o
527 SOBJS += $(AESOBJS)
528+ifneq ($(CONFIG_TLS), mbedtls)
529 SOBJS += ../src/crypto/sha256-prf.o
530 SOBJS += ../src/crypto/sha384-prf.o
531 SOBJS += ../src/crypto/sha512-prf.o
532+endif
533 SOBJS += ../src/crypto/dh_groups.o
534+ifneq ($(CONFIG_TLS), mbedtls)
535 SOBJS += ../src/crypto/sha256-kdf.o
536 SOBJS += ../src/crypto/sha384-kdf.o
537 SOBJS += ../src/crypto/sha512-kdf.o
538+endif
539
540 _OBJS_VAR := NOBJS
541 include ../src/objs.mk
542@@ -1385,6 +1516,12 @@ include ../src/objs.mk
543 _OBJS_VAR := SOBJS
544 include ../src/objs.mk
545
546+dump_cflags:
547+ @printf "%s " "$(CFLAGS)"
548+
549+dump_ldflags:
550+ @printf "%s " "$(LDFLAGS) $(LIBS) $(EXTRALIBS)"
551+
552 nt_password_hash: $(NOBJS)
553 $(Q)$(CC) $(LDFLAGS) -o nt_password_hash $(NOBJS) $(LIBS_n)
554 @$(E) " LD " $@
555diff --git a/hostapd/config_file.c b/hostapd/config_file.c
556index 261905368..0094db279 100644
557--- a/hostapd/config_file.c
558+++ b/hostapd/config_file.c
559@@ -1229,6 +1229,8 @@ static int hostapd_config_vht_capab(struct hostapd_config *conf,
560 conf->vht_capab |= VHT_CAP_RX_ANTENNA_PATTERN;
561 if (os_strstr(capab, "[TX-ANTENNA-PATTERN]"))
562 conf->vht_capab |= VHT_CAP_TX_ANTENNA_PATTERN;
563+ if (os_strstr(capab, "[EXT-NSS-BW-SUPP]"))
564+ conf->vht_capab |= VHT_CAP_EXTENDED_NSS_BW_SUPPORT;
565 return 0;
566 }
567 #endif /* CONFIG_IEEE80211AC */
568@@ -1678,6 +1680,8 @@ static int parse_anqp_elem(struct hostapd_bss_config *bss, char *buf, int line)
569 return 0;
570 }
571
572+#endif /* CONFIG_INTERWORKING */
573+
574
575 static int parse_qos_map_set(struct hostapd_bss_config *bss,
576 char *buf, int line)
577@@ -1719,8 +1723,6 @@ static int parse_qos_map_set(struct hostapd_bss_config *bss,
578 return 0;
579 }
580
581-#endif /* CONFIG_INTERWORKING */
582-
583
584 #ifdef CONFIG_HS20
585 static int hs20_parse_conn_capab(struct hostapd_bss_config *bss, char *buf,
586@@ -2630,8 +2632,12 @@ static int hostapd_config_fill(struct hostapd_config *conf,
587 sizeof(conf->bss[0]->iface));
588 } else if (os_strcmp(buf, "bridge") == 0) {
589 os_strlcpy(bss->bridge, pos, sizeof(bss->bridge));
590+ if (!bss->wds_bridge[0])
591+ os_strlcpy(bss->wds_bridge, pos, sizeof(bss->wds_bridge));
592 } else if (os_strcmp(buf, "bridge_hairpin") == 0) {
593 bss->bridge_hairpin = atoi(pos);
594+ } else if (os_strcmp(buf, "snoop_iface") == 0) {
595+ os_strlcpy(bss->snoop_iface, pos, sizeof(bss->snoop_iface));
596 } else if (os_strcmp(buf, "vlan_bridge") == 0) {
597 os_strlcpy(bss->vlan_bridge, pos, sizeof(bss->vlan_bridge));
598 } else if (os_strcmp(buf, "wds_bridge") == 0) {
599@@ -2998,6 +3004,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
600 } else if (os_strcmp(buf, "iapp_interface") == 0) {
601 wpa_printf(MSG_INFO, "DEPRECATED: iapp_interface not used");
602 #endif /* CONFIG_IAPP */
603+ } else if (os_strcmp(buf, "dynamic_own_ip_addr") == 0) {
604+ bss->dynamic_own_ip_addr = atoi(pos);
605 } else if (os_strcmp(buf, "own_ip_addr") == 0) {
606 if (hostapd_parse_ip_addr(pos, &bss->own_ip_addr)) {
607 wpa_printf(MSG_ERROR,
608@@ -3222,6 +3230,14 @@ static int hostapd_config_fill(struct hostapd_config *conf,
609 line, bss->max_num_sta, MAX_STA_COUNT);
610 return 1;
611 }
612+ } else if (os_strcmp(buf, "iface_max_num_sta") == 0) {
613+ conf->max_num_sta = atoi(pos);
614+ if (conf->max_num_sta < 0 ||
615+ conf->max_num_sta > MAX_STA_COUNT) {
616+ wpa_printf(MSG_ERROR, "Line %d: Invalid max_num_sta=%d; allowed range 0..%d",
617+ line, conf->max_num_sta, MAX_STA_COUNT);
618+ return 1;
619+ }
620 } else if (os_strcmp(buf, "wpa") == 0) {
621 bss->wpa = atoi(pos);
622 } else if (os_strcmp(buf, "extended_key_id") == 0) {
623@@ -3373,6 +3389,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
624 wpa_printf(MSG_INFO,
625 "Line %d: Obsolete peerkey parameter ignored", line);
626 #ifdef CONFIG_IEEE80211R_AP
627+ } else if (os_strcmp(buf, "ft_iface") == 0) {
628+ os_strlcpy(bss->ft_iface, pos, sizeof(bss->ft_iface));
629 } else if (os_strcmp(buf, "mobility_domain") == 0) {
630 if (os_strlen(pos) != 2 * MOBILITY_DOMAIN_ID_LEN ||
631 hexstr2bin(pos, bss->mobility_domain,
632@@ -3742,6 +3760,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
633 #ifndef CONFIG_NO_VLAN
634 } else if (os_strcmp(buf, "dynamic_vlan") == 0) {
635 bss->ssid.dynamic_vlan = atoi(pos);
636+ } else if (os_strcmp(buf, "vlan_no_bridge") == 0) {
637+ bss->ssid.vlan_no_bridge = atoi(pos);
638 } else if (os_strcmp(buf, "per_sta_vif") == 0) {
639 bss->ssid.per_sta_vif = atoi(pos);
640 } else if (os_strcmp(buf, "vlan_file") == 0) {
641@@ -3839,6 +3859,10 @@ static int hostapd_config_fill(struct hostapd_config *conf,
642 if (bss->ocv && !bss->ieee80211w)
643 bss->ieee80211w = 1;
644 #endif /* CONFIG_OCV */
645+ } else if (os_strcmp(buf, "noscan") == 0) {
646+ conf->noscan = atoi(pos);
647+ } else if (os_strcmp(buf, "ht_coex") == 0) {
648+ conf->no_ht_coex = !atoi(pos);
649 } else if (os_strcmp(buf, "ieee80211n") == 0) {
650 conf->ieee80211n = atoi(pos);
651 } else if (os_strcmp(buf, "ht_capab") == 0) {
652@@ -3887,6 +3911,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
653 } else if (os_strcmp(buf, "he_bss_color") == 0) {
654 conf->he_op.he_bss_color = atoi(pos) & 0x3f;
655 conf->he_op.he_bss_color_disabled = 0;
656+ if (atoi(pos) > 63)
657+ conf->he_op.he_bss_color = os_random() % 63 + 1;
658 } else if (os_strcmp(buf, "he_bss_color_partial") == 0) {
659 conf->he_op.he_bss_color_partial = atoi(pos);
660 } else if (os_strcmp(buf, "he_default_pe_duration") == 0) {
661@@ -4520,10 +4546,10 @@ static int hostapd_config_fill(struct hostapd_config *conf,
662 bss->gas_frag_limit = val;
663 } else if (os_strcmp(buf, "gas_comeback_delay") == 0) {
664 bss->gas_comeback_delay = atoi(pos);
665+#endif /* CONFIG_INTERWORKING */
666 } else if (os_strcmp(buf, "qos_map_set") == 0) {
667 if (parse_qos_map_set(bss, pos, line) < 0)
668 return 1;
669-#endif /* CONFIG_INTERWORKING */
670 #ifdef CONFIG_RADIUS_TEST
671 } else if (os_strcmp(buf, "dump_msk_file") == 0) {
672 os_free(bss->dump_msk_file);
673@@ -5347,7 +5373,12 @@ struct hostapd_config * hostapd_config_read(const char *fname)
674 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
688index 10cb186f1..f76226cf4 100644
689--- a/hostapd/ctrl_iface.c
690+++ b/hostapd/ctrl_iface.c
691@@ -3876,6 +3876,7 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
692 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) {
699@@ -3917,6 +3918,7 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
700 } 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;
707@@ -5464,6 +5466,7 @@ try_again:
708 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;
715@@ -5565,6 +5568,7 @@ fail:
716 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
759index a9d326de8..a469b1f4d 100644
760--- a/hostapd/hostapd_cli.c
761+++ b/hostapd/hostapd_cli.c
762@@ -401,7 +401,6 @@ static int hostapd_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
763 }
764
765
766-#ifdef CONFIG_TAXONOMY
767 static int hostapd_cli_cmd_signature(struct wpa_ctrl *ctrl, int argc,
768 char *argv[])
769 {
770@@ -414,7 +413,6 @@ static int hostapd_cli_cmd_signature(struct wpa_ctrl *ctrl, int argc,
771 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,
778@@ -431,7 +429,6 @@ static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
779 }
780
781
782-#ifdef CONFIG_WPS
783 static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,
784 char *argv[])
785 {
786@@ -657,7 +654,6 @@ static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
787 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,
794@@ -757,7 +753,7 @@ static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, const char *cmd,
795 }
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);
803@@ -1670,13 +1666,10 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
804 { "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,
817@@ -1701,7 +1694,6 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
818 "<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
826index 524a10274..0ccd4a5d7 100644
827--- 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,
846@@ -690,6 +691,11 @@ fail:
847 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)
858@@ -781,6 +787,11 @@ int main(int argc, char *argv[])
859 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;
870@@ -806,8 +817,10 @@ int main(int argc, char *argv[])
871 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) {
882@@ -844,6 +857,8 @@ int main(int argc, char *argv[])
883 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':
891@@ -1013,6 +1028,7 @@ int main(int argc, char *argv[])
892 }
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");
899@@ -1022,6 +1038,7 @@ int main(int argc, char *argv[])
900 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
908index 28b0ba71c..4c4c750ab 100644
909--- a/src/ap/acs.c
910+++ b/src/ap/acs.c
911@@ -467,17 +467,17 @@ static int acs_get_bw_center_chan(int freq, enum bw_type bw)
912 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) &&
931@@ -485,7 +485,6 @@ static int acs_survey_is_sufficient(struct freq_survey *survey)
932 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
973index 2330163c4..d10b00be9 100644
974--- 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;
1000 int acct_interim_interval;
1001@@ -1064,6 +1068,8 @@ struct hostapd_config {
1002 unsigned int track_sta_max_num;
1003 unsigned int track_sta_max_age;
1004
1005+ int max_num_sta;
1006+
1007 char country[3]; /* first two octets: country code as described in
1008 * ISO/IEC 3166-1. Third octet:
1009 * ' ' (ascii 32): all environments
1010@@ -1101,6 +1107,8 @@ struct hostapd_config {
1011
1012 int ht_op_mode_fixed;
1013 u16 ht_capab;
1014+ int noscan;
1015+ int no_ht_coex;
1016 int ieee80211n;
1017 int secondary_channel;
1018 int no_pri_sec_switch;
1019diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
1020index 32722084d..527b2c984 100644
1021--- a/src/ap/ap_drv_ops.c
1022+++ b/src/ap/ap_drv_ops.c
1023@@ -387,8 +387,6 @@ int hostapd_set_wds_sta(struct hostapd_data *hapd, char *ifname_wds,
1024 return -1;
1025 if (hapd->conf->wds_bridge[0])
1026 bridge = hapd->conf->wds_bridge;
1027- else if (hapd->conf->bridge[0])
1028- bridge = hapd->conf->bridge;
1029 return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val,
1030 bridge, ifname_wds);
1031 }
1032@@ -1031,7 +1029,8 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface,
1033 int hostapd_drv_set_qos_map(struct hostapd_data *hapd,
1034 const u8 *qos_map_set, u8 qos_map_set_len)
1035 {
1036- if (!hapd->driver || !hapd->driver->set_qos_map || !hapd->drv_priv)
1037+ if (!hapd->driver || !hapd->driver->set_qos_map || !hapd->drv_priv ||
1038+ !(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING))
1039 return 0;
1040 return hapd->driver->set_qos_map(hapd->drv_priv, qos_map_set,
1041 qos_map_set_len);
1042diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
1043index d7e79c840..f8a8725be 100644
1044--- a/src/ap/ap_drv_ops.h
1045+++ b/src/ap/ap_drv_ops.h
1046@@ -371,12 +371,12 @@ static inline int hostapd_drv_br_port_set_attr(struct hostapd_data *hapd,
1047
1048 static inline int hostapd_drv_br_set_net_param(struct hostapd_data *hapd,
1049 enum drv_br_net_param param,
1050- unsigned int val)
1051+ const char *ifname, unsigned int val)
1052 {
1053 if (hapd->driver == NULL || hapd->drv_priv == NULL ||
1054 hapd->driver->br_set_net_param == NULL)
1055 return -1;
1056- return hapd->driver->br_set_net_param(hapd->drv_priv, param, val);
1057+ return hapd->driver->br_set_net_param(hapd->drv_priv, param, ifname, val);
1058 }
1059
1060 static inline int hostapd_drv_vendor_cmd(struct hostapd_data *hapd,
1061@@ -404,6 +404,23 @@ static inline int hostapd_drv_stop_ap(struct hostapd_data *hapd)
1062 return hapd->driver->stop_ap(hapd->drv_priv, link_id);
1063 }
1064
1065+static inline int hostapd_drv_if_rename(struct hostapd_data *hapd,
1066+ enum wpa_driver_if_type type,
1067+ const char *ifname,
1068+ const char *new_name)
1069+{
1070+ if (!hapd->driver || !hapd->driver->if_rename || !hapd->drv_priv)
1071+ return -1;
1072+ return hapd->driver->if_rename(hapd->drv_priv, type, ifname, new_name);
1073+}
1074+
1075+static inline int hostapd_drv_set_first_bss(struct hostapd_data *hapd)
1076+{
1077+ if (!hapd->driver || !hapd->driver->set_first_bss || !hapd->drv_priv)
1078+ return 0;
1079+ return hapd->driver->set_first_bss(hapd->drv_priv);
1080+}
1081+
1082 static inline int hostapd_drv_channel_info(struct hostapd_data *hapd,
1083 struct wpa_channel_info *ci)
1084 {
1085diff --git a/src/ap/beacon.c b/src/ap/beacon.c
1086index 4354dfae3..26453cb2c 100644
1087--- a/src/ap/beacon.c
1088+++ b/src/ap/beacon.c
1089@@ -1343,6 +1343,12 @@ void handle_probe_req(struct hostapd_data *hapd,
1090 int mld_id;
1091 u16 links;
1092 #endif /* CONFIG_IEEE80211BE */
1093+ struct hostapd_ubus_request req = {
1094+ .type = HOSTAPD_UBUS_PROBE_REQ,
1095+ .mgmt_frame = mgmt,
1096+ .ssi_signal = ssi_signal,
1097+ .elems = &elems,
1098+ };
1099
1100 if (hapd->iconf->rssi_ignore_probe_request && ssi_signal &&
1101 ssi_signal < hapd->iconf->rssi_ignore_probe_request)
1102@@ -1529,6 +1535,12 @@ void handle_probe_req(struct hostapd_data *hapd,
1103 }
1104 #endif /* CONFIG_P2P */
1105
1106+ if (hostapd_ubus_handle_event(hapd, &req)) {
1107+ wpa_printf(MSG_DEBUG, "Probe request for " MACSTR " rejected by ubus handler.\n",
1108+ MAC2STR(mgmt->sa));
1109+ return;
1110+ }
1111+
1112 /* TODO: verify that supp_rates contains at least one matching rate
1113 * with AP configuration */
1114
1115@@ -1547,7 +1559,7 @@ void handle_probe_req(struct hostapd_data *hapd,
1116 if (hapd->conf->no_probe_resp_if_max_sta &&
1117 is_multicast_ether_addr(mgmt->da) &&
1118 is_multicast_ether_addr(mgmt->bssid) &&
1119- hapd->num_sta >= hapd->conf->max_num_sta &&
1120+ hostapd_check_max_sta(hapd) &&
1121 !ap_get_sta(hapd, mgmt->sa)) {
1122 wpa_printf(MSG_MSGDUMP, "%s: Ignore Probe Request from " MACSTR
1123 " since no room for additional STA",
1124diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
1125index 2cfef4bd4..cd7db4fc6 100644
1126--- a/src/ap/ctrl_iface_ap.c
1127+++ b/src/ap/ctrl_iface_ap.c
1128@@ -26,6 +26,26 @@
1129 #include "taxonomy.h"
1130 #include "wnm_ap.h"
1131
1132+static const char * hw_mode_str(enum hostapd_hw_mode mode)
1133+{
1134+ switch (mode) {
1135+ case HOSTAPD_MODE_IEEE80211B:
1136+ return "b";
1137+ case HOSTAPD_MODE_IEEE80211G:
1138+ return "g";
1139+ case HOSTAPD_MODE_IEEE80211A:
1140+ return "a";
1141+ case HOSTAPD_MODE_IEEE80211AD:
1142+ return "ad";
1143+ case HOSTAPD_MODE_IEEE80211ANY:
1144+ return "any";
1145+ case NUM_HOSTAPD_MODES:
1146+ return "invalid";
1147+ }
1148+ return "unknown";
1149+}
1150+
1151+#ifdef CONFIG_CTRL_IFACE_MIB
1152
1153 static size_t hostapd_write_ht_mcs_bitmask(char *buf, size_t buflen,
1154 size_t curr_len, const u8 *mcs_set)
1155@@ -212,26 +232,6 @@ static const char * timeout_next_str(int val)
1156 }
1157
1158
1159-static const char * hw_mode_str(enum hostapd_hw_mode mode)
1160-{
1161- switch (mode) {
1162- case HOSTAPD_MODE_IEEE80211B:
1163- return "b";
1164- case HOSTAPD_MODE_IEEE80211G:
1165- return "g";
1166- case HOSTAPD_MODE_IEEE80211A:
1167- return "a";
1168- case HOSTAPD_MODE_IEEE80211AD:
1169- return "ad";
1170- case HOSTAPD_MODE_IEEE80211ANY:
1171- return "any";
1172- case NUM_HOSTAPD_MODES:
1173- return "invalid";
1174- }
1175- return "unknown";
1176-}
1177-
1178-
1179 static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
1180 struct sta_info *sta,
1181 char *buf, size_t buflen)
1182@@ -539,6 +539,7 @@ int hostapd_ctrl_iface_sta_next(struct hostapd_data *hapd, const char *txtaddr,
1183 return hostapd_ctrl_iface_sta_mib(hapd, sta->next, buf, buflen);
1184 }
1185
1186+#endif
1187
1188 #ifdef CONFIG_P2P_MANAGER
1189 static int p2p_manager_disconnect(struct hostapd_data *hapd, u16 stype,
1190@@ -987,12 +988,12 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
1191 return len;
1192 len += ret;
1193 }
1194-
1195+#ifdef CONFIG_CTRL_IFACE_MIB
1196 if (iface->conf->ieee80211n && !hapd->conf->disable_11n && mode) {
1197 len = hostapd_write_ht_mcs_bitmask(buf, buflen, len,
1198 mode->mcs_set);
1199 }
1200-
1201+#endif /* CONFIG_CTRL_IFACE_MIB */
1202 if (iface->current_rates && iface->num_rates) {
1203 ret = os_snprintf(buf + len, buflen - len, "supported_rates=");
1204 if (os_snprintf_error(buflen - len, ret))
1205diff --git a/src/ap/dfs.c b/src/ap/dfs.c
1206index fc2e8d83c..d14fad136 100644
1207--- a/src/ap/dfs.c
1208+++ b/src/ap/dfs.c
1209@@ -17,6 +17,7 @@
1210 #include "ap_drv_ops.h"
1211 #include "drivers/driver.h"
1212 #include "dfs.h"
1213+#include "crypto/crypto.h"
1214
1215
1216 enum dfs_channel_type {
1217@@ -526,9 +527,14 @@ dfs_get_valid_channel(struct hostapd_iface *iface,
1218 int num_available_chandefs;
1219 int chan_idx, chan_idx2;
1220 int sec_chan_idx_80p80 = -1;
1221+ bool is_mesh = false;
1222 int i;
1223 u32 _rand;
1224
1225+#ifdef CONFIG_MESH
1226+ is_mesh = iface->mconf;
1227+#endif
1228+
1229 wpa_printf(MSG_DEBUG, "DFS: Selecting random channel");
1230 *secondary_channel = 0;
1231 *oper_centr_freq_seg0_idx = 0;
1232@@ -548,8 +554,20 @@ dfs_get_valid_channel(struct hostapd_iface *iface,
1233 if (num_available_chandefs == 0)
1234 return NULL;
1235
1236- if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0)
1237+ /* try to use deterministic channel in mesh, so that both sides
1238+ * have a chance to switch to the same channel */
1239+ if (is_mesh) {
1240+#ifdef CONFIG_MESH
1241+ u64 hash[4];
1242+ const u8 *meshid[1] = { &iface->mconf->meshid[0] };
1243+ const size_t meshid_len = iface->mconf->meshid_len;
1244+
1245+ sha256_vector(1, meshid, &meshid_len, (u8 *)&hash[0]);
1246+ _rand = hash[0] + hash[1] + hash[2] + hash[3];
1247+#endif
1248+ } else if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0)
1249 return NULL;
1250+
1251 chan_idx = _rand % num_available_chandefs;
1252 wpa_printf(MSG_DEBUG, "DFS: Picked random entry from the list: %d/%d",
1253 chan_idx, num_available_chandefs);
1254@@ -1207,6 +1225,8 @@ int hostapd_dfs_pre_cac_expired(struct hostapd_iface *iface, int freq,
1255 "freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d",
1256 freq, ht_enabled, chan_offset, chan_width, cf1, cf2);
1257
1258+ hostapd_ubus_notify_radar_detected(iface, freq, chan_width, cf1, cf2);
1259+
1260 /* Proceed only if DFS is not offloaded to the driver */
1261 if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)
1262 return 0;
1263diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
1264index dc21977ff..e8796f709 100644
1265--- a/src/ap/drv_callbacks.c
1266+++ b/src/ap/drv_callbacks.c
1267@@ -268,6 +268,10 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
1268 struct hostapd_iface *iface = hapd->iface;
1269 #endif /* CONFIG_OWE */
1270 bool updated = false;
1271+ struct hostapd_ubus_request req = {
1272+ .type = HOSTAPD_UBUS_ASSOC_REQ,
1273+ .addr = addr,
1274+ };
1275
1276 if (addr == NULL) {
1277 /*
1278@@ -412,6 +416,12 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
1279 goto fail;
1280 }
1281
1282+ if (hostapd_ubus_handle_event(hapd, &req)) {
1283+ wpa_printf(MSG_DEBUG, "Station " MACSTR " assoc rejected by ubus handler.\n",
1284+ MAC2STR(req.addr));
1285+ goto fail;
1286+ }
1287+
1288 #ifdef CONFIG_P2P
1289 if (elems.p2p) {
1290 wpabuf_free(sta->p2p_ie);
1291@@ -2342,8 +2352,8 @@ static void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst,
1292 ieee802_1x_eapol_tx_status(hapd, sta, data, len, ack);
1293 }
1294
1295-void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
1296- union wpa_event_data *data)
1297+void hostapd_wpa_event(void *ctx, enum wpa_event_type event,
1298+ union wpa_event_data *data)
1299 {
1300 struct hostapd_data *hapd = ctx;
1301 struct sta_info *sta;
1302@@ -2675,7 +2685,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
1303 }
1304
1305
1306-void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
1307+void hostapd_wpa_event_global(void *ctx, enum wpa_event_type event,
1308 union wpa_event_data *data)
1309 {
1310 struct hapd_interfaces *interfaces = ctx;
1311diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
1312index b899c9831..7959859b0 100644
1313--- a/src/ap/hostapd.c
1314+++ b/src/ap/hostapd.c
1315@@ -247,6 +247,29 @@ static int hostapd_iface_conf_changed(struct hostapd_config *newconf,
1316 return 0;
1317 }
1318
1319+static inline int hostapd_iface_num_sta(struct hostapd_iface *iface)
1320+{
1321+ int num_sta = 0;
1322+ int i;
1323+
1324+ for (i = 0; i < iface->num_bss; i++)
1325+ num_sta += iface->bss[i]->num_sta;
1326+
1327+ return num_sta;
1328+}
1329+
1330+
1331+int hostapd_check_max_sta(struct hostapd_data *hapd)
1332+{
1333+ if (hapd->num_sta >= hapd->conf->max_num_sta)
1334+ return 1;
1335+
1336+ if (hapd->iconf->max_num_sta &&
1337+ hostapd_iface_num_sta(hapd->iface) >= hapd->iconf->max_num_sta)
1338+ return 1;
1339+
1340+ return 0;
1341+}
1342
1343 int hostapd_reload_config(struct hostapd_iface *iface)
1344 {
1345@@ -255,6 +278,8 @@ int hostapd_reload_config(struct hostapd_iface *iface)
1346 struct hostapd_config *newconf, *oldconf;
1347 size_t j;
1348
1349+ hostapd_ucode_reload_bss(hapd);
1350+
1351 if (iface->config_fname == NULL) {
1352 /* Only in-memory config in use - assume it has been updated */
1353 hostapd_clear_old(iface);
1354@@ -475,6 +500,8 @@ void hostapd_free_hapd_data(struct hostapd_data *hapd)
1355 hapd->beacon_set_done = 0;
1356
1357 wpa_printf(MSG_DEBUG, "%s(%s)", __func__, hapd->conf->iface);
1358+ hostapd_ucode_free_bss(hapd);
1359+ hostapd_ubus_free_bss(hapd);
1360 accounting_deinit(hapd);
1361 hostapd_deinit_wpa(hapd);
1362 vlan_deinit(hapd);
1363@@ -685,6 +712,7 @@ static void sta_track_deinit(struct hostapd_iface *iface)
1364 void hostapd_cleanup_iface_partial(struct hostapd_iface *iface)
1365 {
1366 wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
1367+ eloop_cancel_timeout(channel_list_update_timeout, iface, NULL);
1368 #ifdef NEED_AP_MLME
1369 hostapd_stop_setup_timers(iface);
1370 #endif /* NEED_AP_MLME */
1371@@ -714,7 +742,7 @@ void hostapd_cleanup_iface_partial(struct hostapd_iface *iface)
1372 static void hostapd_cleanup_iface(struct hostapd_iface *iface)
1373 {
1374 wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
1375- eloop_cancel_timeout(channel_list_update_timeout, iface, NULL);
1376+ hostapd_ucode_free_iface(iface);
1377 eloop_cancel_timeout(hostapd_interface_setup_failure_handler, iface,
1378 NULL);
1379
1380@@ -1303,6 +1331,9 @@ static int hostapd_start_beacon(struct hostapd_data *hapd,
1381 if (hapd->driver && hapd->driver->set_operstate)
1382 hapd->driver->set_operstate(hapd->drv_priv, 1);
1383
1384+ hostapd_ubus_add_bss(hapd);
1385+ hostapd_ucode_add_bss(hapd);
1386+
1387 return 0;
1388 }
1389
1390@@ -1324,8 +1355,7 @@ static int hostapd_start_beacon(struct hostapd_data *hapd,
1391 * initialized. Most of the modules that are initialized here will be
1392 * deinitialized in hostapd_cleanup().
1393 */
1394-static int hostapd_setup_bss(struct hostapd_data *hapd, int first,
1395- bool start_beacon)
1396+int hostapd_setup_bss(struct hostapd_data *hapd, int first, bool start_beacon)
1397 {
1398 struct hostapd_bss_config *conf = hapd->conf;
1399 u8 ssid[SSID_MAX_LEN + 1];
1400@@ -1552,6 +1582,7 @@ setup_mld:
1401
1402 os_memset(&das_conf, 0, sizeof(das_conf));
1403 das_conf.port = conf->radius_das_port;
1404+ das_conf.nas_identifier = conf->nas_identifier;
1405 das_conf.shared_secret = conf->radius_das_shared_secret;
1406 das_conf.shared_secret_len =
1407 conf->radius_das_shared_secret_len;
1408@@ -1627,6 +1658,7 @@ setup_mld:
1409 wpa_printf(MSG_ERROR, "GAS server initialization failed");
1410 return -1;
1411 }
1412+#endif /* CONFIG_INTERWORKING */
1413
1414 if (conf->qos_map_set_len &&
1415 hostapd_drv_set_qos_map(hapd, conf->qos_map_set,
1416@@ -1634,7 +1666,6 @@ setup_mld:
1417 wpa_printf(MSG_ERROR, "Failed to initialize QoS Map");
1418 return -1;
1419 }
1420-#endif /* CONFIG_INTERWORKING */
1421
1422 if (conf->bss_load_update_period && bss_load_update_init(hapd)) {
1423 wpa_printf(MSG_ERROR, "BSS Load initialization failed");
1424@@ -2447,6 +2478,7 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
1425 if (err)
1426 goto fail;
1427
1428+ hostapd_ubus_add_iface(iface);
1429 wpa_printf(MSG_DEBUG, "Completing interface initialization");
1430 if (iface->freq) {
1431 #ifdef NEED_AP_MLME
1432@@ -2676,6 +2708,7 @@ dfs_offload:
1433
1434 fail:
1435 wpa_printf(MSG_ERROR, "Interface initialization failed");
1436+ hostapd_ubus_free_iface(iface);
1437
1438 if (iface->is_no_ir) {
1439 hostapd_set_state(iface, HAPD_IFACE_NO_IR);
1440@@ -2875,7 +2908,7 @@ hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface,
1441 }
1442
1443
1444-static void hostapd_bss_deinit(struct hostapd_data *hapd)
1445+void hostapd_bss_deinit(struct hostapd_data *hapd)
1446 {
1447 if (!hapd)
1448 return;
1449@@ -3395,6 +3428,7 @@ void hostapd_interface_deinit_free(struct hostapd_iface *iface)
1450 (unsigned int) iface->conf->num_bss);
1451 driver = iface->bss[0]->driver;
1452 drv_priv = iface->bss[0]->drv_priv;
1453+ hostapd_ubus_free_iface(iface);
1454 hostapd_interface_deinit(iface);
1455 wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit",
1456 __func__, driver, drv_priv);
1457@@ -3926,7 +3960,8 @@ int hostapd_remove_iface(struct hapd_interfaces *interfaces, char *buf)
1458 hapd_iface = interfaces->iface[i];
1459 if (hapd_iface == NULL)
1460 return -1;
1461- if (!os_strcmp(hapd_iface->conf->bss[0]->iface, buf)) {
1462+ if (!os_strcmp(hapd_iface->phy, buf) ||
1463+ !os_strcmp(hapd_iface->conf->bss[0]->iface, buf)) {
1464 wpa_printf(MSG_INFO, "Remove interface '%s'", buf);
1465 hapd_iface->driver_ap_teardown =
1466 !!(hapd_iface->drv_flags &
1467@@ -3972,6 +4007,8 @@ int hostapd_remove_iface(struct hapd_interfaces *interfaces, char *buf)
1468 void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
1469 int reassoc)
1470 {
1471+ int mld_assoc_link_id = -1;
1472+
1473 if (hapd->tkip_countermeasures) {
1474 hostapd_drv_sta_deauth(hapd, sta->addr,
1475 WLAN_REASON_MICHAEL_MIC_FAILURE);
1476@@ -3983,6 +4020,8 @@ void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
1477 sta->mld_assoc_link_id != hapd->mld_link_id)
1478 return;
1479 #endif /* CONFIG_IEEE80211BE */
1480+ if (mld_assoc_link_id != -2)
1481+ hostapd_prune_associations(hapd, sta->addr, mld_assoc_link_id);
1482
1483 ap_sta_clear_disconnect_timeouts(hapd, sta);
1484 sta->post_csa_sa_query = 0;
1485diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
1486index 594866fbb..1e4113459 100644
1487--- a/src/ap/hostapd.h
1488+++ b/src/ap/hostapd.h
1489@@ -13,11 +13,14 @@
1490 #include <sqlite3.h>
1491 #endif /* CONFIG_SQLITE */
1492
1493+#include "ap/sta_info.h"
1494 #include "common/defs.h"
1495 #include "common/dpp.h"
1496 #include "utils/list.h"
1497 #include "ap_config.h"
1498 #include "drivers/driver.h"
1499+#include "ubus.h"
1500+#include "ucode.h"
1501
1502 #define OCE_STA_CFON_ENABLED(hapd) \
1503 ((hapd->conf->oce & OCE_STA_CFON) && \
1504@@ -51,6 +54,10 @@ struct hapd_interfaces {
1505 struct hostapd_config * (*config_read_cb)(const char *config_fname);
1506 int (*ctrl_iface_init)(struct hostapd_data *hapd);
1507 void (*ctrl_iface_deinit)(struct hostapd_data *hapd);
1508+ int (*ctrl_iface_recv)(struct hostapd_data *hapd,
1509+ char *buf, char *reply, int reply_size,
1510+ struct sockaddr_storage *from,
1511+ socklen_t fromlen);
1512 int (*for_each_interface)(struct hapd_interfaces *interfaces,
1513 int (*cb)(struct hostapd_iface *iface,
1514 void *ctx), void *ctx);
1515@@ -167,6 +174,21 @@ struct hostapd_sae_commit_queue {
1516 u8 msg[];
1517 };
1518
1519+/**
1520+ * struct hostapd_openwrt_stats - OpenWrt custom STA/AP statistics
1521+ */
1522+struct hostapd_openwrt_stats {
1523+ struct {
1524+ u64 neighbor_report_tx;
1525+ } rrm;
1526+
1527+ struct {
1528+ u64 bss_transition_query_rx;
1529+ u64 bss_transition_request_tx;
1530+ u64 bss_transition_response_rx;
1531+ } wnm;
1532+};
1533+
1534 /**
1535 * struct hostapd_data - hostapd per-BSS data structure
1536 */
1537@@ -174,6 +196,8 @@ struct hostapd_data {
1538 struct hostapd_iface *iface;
1539 struct hostapd_config *iconf;
1540 struct hostapd_bss_config *conf;
1541+ struct hostapd_ubus_bss ubus;
1542+ struct hostapd_ucode_bss ucode;
1543 int interface_added; /* virtual interface added for this BSS */
1544 unsigned int started:1;
1545 unsigned int disabled:1;
1546@@ -181,6 +205,9 @@ struct hostapd_data {
1547
1548 u8 own_addr[ETH_ALEN];
1549
1550+ /* OpenWrt specific statistics */
1551+ struct hostapd_openwrt_stats openwrt_stats;
1552+
1553 int num_sta; /* number of entries in sta_list */
1554 struct sta_info *sta_list; /* STA info list head */
1555 #define STA_HASH_SIZE 256
1556@@ -523,6 +550,7 @@ struct hostapd_mld {
1557 */
1558 struct hostapd_iface {
1559 struct hapd_interfaces *interfaces;
1560+ struct hostapd_ucode_iface ucode;
1561 void *owner;
1562 char *config_fname;
1563 struct hostapd_config *conf;
1564@@ -745,6 +773,7 @@ hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface,
1565 struct hostapd_bss_config *bss);
1566 int hostapd_setup_interface(struct hostapd_iface *iface);
1567 int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err);
1568+void hostapd_set_own_neighbor_report(struct hostapd_data *hapd);
1569 void hostapd_interface_deinit(struct hostapd_iface *iface);
1570 void hostapd_interface_free(struct hostapd_iface *iface);
1571 struct hostapd_iface * hostapd_alloc_iface(void);
1572@@ -753,6 +782,8 @@ struct hostapd_iface * hostapd_init(struct hapd_interfaces *interfaces,
1573 struct hostapd_iface *
1574 hostapd_interface_init_bss(struct hapd_interfaces *interfaces, const char *phy,
1575 const char *config_fname, int debug);
1576+int hostapd_setup_bss(struct hostapd_data *hapd, int first, bool start_beacon);
1577+void hostapd_bss_deinit(struct hostapd_data *hapd);
1578 void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
1579 int reassoc);
1580 void hostapd_interface_deinit_free(struct hostapd_iface *iface);
1581@@ -780,6 +811,7 @@ void hostapd_cleanup_cs_params(struct hostapd_data *hapd);
1582 void hostapd_periodic_iface(struct hostapd_iface *iface);
1583 int hostapd_owe_trans_get_info(struct hostapd_data *hapd);
1584 void hostapd_ocv_check_csa_sa_query(void *eloop_ctx, void *timeout_ctx);
1585+int hostapd_check_max_sta(struct hostapd_data *hapd);
1586
1587 void hostapd_switch_color(struct hostapd_data *hapd, u64 bitmap);
1588 void hostapd_cleanup_cca_params(struct hostapd_data *hapd);
1589@@ -865,4 +897,14 @@ static inline bool hostapd_mld_is_first_bss(struct hostapd_data *hapd)
1590
1591 u16 hostapd_get_punct_bitmap(struct hostapd_data *hapd);
1592
1593+static inline bool ap_sta_is_mld(struct hostapd_data *hapd,
1594+ struct sta_info *sta)
1595+{
1596+#ifdef CONFIG_IEEE80211BE
1597+ return hapd->conf->mld_ap && sta && sta->mld_info.mld_sta;
1598+#else /* CONFIG_IEEE80211BE */
1599+ return false;
1600+#endif /* CONFIG_IEEE80211BE */
1601+}
1602+
1603 #endif /* HOSTAPD_H */
1604diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
1605index 222f3dc05..672e43a10 100644
1606--- a/src/ap/hw_features.c
1607+++ b/src/ap/hw_features.c
1608@@ -546,7 +546,8 @@ static int ieee80211n_check_40mhz(struct hostapd_iface *iface)
1609 int ret;
1610
1611 /* Check that HT40 is used and PRI / SEC switch is allowed */
1612- if (!iface->conf->secondary_channel || iface->conf->no_pri_sec_switch)
1613+ if (!iface->conf->secondary_channel || iface->conf->no_pri_sec_switch ||
1614+ iface->conf->noscan)
1615 return 0;
1616
1617 hostapd_set_state(iface, HAPD_IFACE_HT_SCAN);
1618diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
1619index 179af5e28..bda61b998 100644
1620--- a/src/ap/ieee802_11.c
1621+++ b/src/ap/ieee802_11.c
1622@@ -2804,7 +2804,7 @@ static void handle_auth(struct hostapd_data *hapd,
1623 u16 auth_alg, auth_transaction, status_code;
1624 u16 resp = WLAN_STATUS_SUCCESS;
1625 struct sta_info *sta = NULL;
1626- int res, reply_res;
1627+ int res, reply_res, ubus_resp;
1628 u16 fc;
1629 const u8 *challenge = NULL;
1630 u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
1631@@ -2815,6 +2815,11 @@ static void handle_auth(struct hostapd_data *hapd,
1632 #ifdef CONFIG_IEEE80211BE
1633 bool mld_sta = false;
1634 #endif /* CONFIG_IEEE80211BE */
1635+ struct hostapd_ubus_request req = {
1636+ .type = HOSTAPD_UBUS_AUTH_REQ,
1637+ .mgmt_frame = mgmt,
1638+ .ssi_signal = rssi,
1639+ };
1640
1641 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
1642 wpa_printf(MSG_INFO, "handle_auth - too short payload (len=%lu)",
1643@@ -3008,6 +3013,13 @@ static void handle_auth(struct hostapd_data *hapd,
1644 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1645 goto fail;
1646 }
1647+ ubus_resp = hostapd_ubus_handle_event(hapd, &req);
1648+ if (ubus_resp) {
1649+ wpa_printf(MSG_DEBUG, "Station " MACSTR " rejected by ubus handler.\n",
1650+ MAC2STR(mgmt->sa));
1651+ resp = ubus_resp > 0 ? (u16) ubus_resp : WLAN_STATUS_UNSPECIFIED_FAILURE;
1652+ goto fail;
1653+ }
1654 if (res == HOSTAPD_ACL_PENDING)
1655 return;
1656
1657@@ -3042,15 +3054,6 @@ static void handle_auth(struct hostapd_data *hapd,
1658 seq_ctrl);
1659 return;
1660 }
1661-#ifdef CONFIG_MESH
1662- if ((hapd->conf->mesh & MESH_ENABLED) &&
1663- sta->plink_state == PLINK_BLOCKED) {
1664- wpa_printf(MSG_DEBUG, "Mesh peer " MACSTR
1665- " is blocked - drop Authentication frame",
1666- MAC2STR(sa));
1667- return;
1668- }
1669-#endif /* CONFIG_MESH */
1670 #ifdef CONFIG_PASN
1671 if (auth_alg == WLAN_AUTH_PASN &&
1672 (sta->flags & WLAN_STA_ASSOC)) {
1673@@ -4698,6 +4701,13 @@ static int add_associated_sta(struct hostapd_data *hapd,
1674 * drivers to accept the STA parameter configuration. Since this is
1675 * after a new FT-over-DS exchange, a new TK has been derived, so key
1676 * reinstallation is not a concern for this case.
1677+ *
1678+ * If the STA was associated and authorized earlier, but came for a new
1679+ * connection (!added_unassoc + !reassoc), remove the existing STA entry
1680+ * so that it can be re-added. This case is rarely seen when the AP could
1681+ * not receive the deauth/disassoc frame from the STA. And the STA comes
1682+ * back with new connection within a short period or before the inactive
1683+ * STA entry is removed from the list.
1684 */
1685 wpa_printf(MSG_DEBUG, "Add associated STA " MACSTR
1686 " (added_unassoc=%d auth_alg=%u ft_over_ds=%u reassoc=%d authorized=%d ft_tk=%d fils_tk=%d)",
1687@@ -4711,7 +4721,8 @@ static int add_associated_sta(struct hostapd_data *hapd,
1688 (!(sta->flags & WLAN_STA_AUTHORIZED) ||
1689 (reassoc && sta->ft_over_ds && sta->auth_alg == WLAN_AUTH_FT) ||
1690 (!wpa_auth_sta_ft_tk_already_set(sta->wpa_sm) &&
1691- !wpa_auth_sta_fils_tk_already_set(sta->wpa_sm)))) {
1692+ !wpa_auth_sta_fils_tk_already_set(sta->wpa_sm)) ||
1693+ (!reassoc && (sta->flags & WLAN_STA_AUTHORIZED)))) {
1694 hostapd_drv_sta_remove(hapd, sta->addr);
1695 wpa_auth_sm_event(sta->wpa_sm, WPA_DRV_STA_REMOVED);
1696 set = 0;
1697@@ -5273,7 +5284,7 @@ static void handle_assoc(struct hostapd_data *hapd,
1698 int resp = WLAN_STATUS_SUCCESS;
1699 u16 reply_res = WLAN_STATUS_UNSPECIFIED_FAILURE;
1700 const u8 *pos;
1701- int left, i;
1702+ int left, i, ubus_resp;
1703 struct sta_info *sta;
1704 u8 *tmp = NULL;
1705 #ifdef CONFIG_FILS
1706@@ -5515,6 +5526,11 @@ static void handle_assoc(struct hostapd_data *hapd,
1707 left = res;
1708 }
1709 #endif /* CONFIG_FILS */
1710+ struct hostapd_ubus_request req = {
1711+ .type = HOSTAPD_UBUS_ASSOC_REQ,
1712+ .mgmt_frame = mgmt,
1713+ .ssi_signal = rssi,
1714+ };
1715
1716 /* followed by SSID and Supported rates; and HT capabilities if 802.11n
1717 * is used */
1718@@ -5617,6 +5633,13 @@ static void handle_assoc(struct hostapd_data *hapd,
1719 if (set_beacon)
1720 ieee802_11_set_beacons(hapd->iface);
1721
1722+ ubus_resp = hostapd_ubus_handle_event(hapd, &req);
1723+ if (ubus_resp) {
1724+ wpa_printf(MSG_DEBUG, "Station " MACSTR " assoc rejected by ubus handler.\n",
1725+ MAC2STR(mgmt->sa));
1726+ resp = ubus_resp > 0 ? (u16) ubus_resp : WLAN_STATUS_UNSPECIFIED_FAILURE;
1727+ goto fail;
1728+ }
1729 fail:
1730
1731 /*
1732@@ -5848,6 +5871,7 @@ static void handle_disassoc(struct hostapd_data *hapd,
1733 (unsigned long) len);
1734 return;
1735 }
1736+ hostapd_ubus_notify(hapd, "disassoc", mgmt->sa);
1737
1738 sta = ap_get_sta(hapd, mgmt->sa);
1739 if (!sta) {
1740@@ -5879,6 +5903,8 @@ static void handle_deauth(struct hostapd_data *hapd,
1741 /* Clear the PTKSA cache entries for PASN */
1742 ptksa_cache_flush(hapd->ptksa, mgmt->sa, WPA_CIPHER_NONE);
1743
1744+ hostapd_ubus_notify(hapd, "deauth", mgmt->sa);
1745+
1746 sta = ap_get_sta(hapd, mgmt->sa);
1747 if (!sta) {
1748 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR
1749diff --git a/src/ap/ieee802_11_ht.c b/src/ap/ieee802_11_ht.c
1750index f90f1254e..7f0a00f95 100644
1751--- a/src/ap/ieee802_11_ht.c
1752+++ b/src/ap/ieee802_11_ht.c
1753@@ -82,7 +82,9 @@ u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid)
1754 u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid)
1755 {
1756 struct ieee80211_ht_operation *oper;
1757+ le32 vht_capabilities_info;
1758 u8 *pos = eid;
1759+ u8 chwidth;
1760
1761 if (!hapd->iconf->ieee80211n || hapd->conf->disable_11n ||
1762 is_6ghz_op_class(hapd->iconf->op_class))
1763@@ -103,6 +105,13 @@ u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid)
1764 oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW |
1765 HT_INFO_HT_PARAM_STA_CHNL_WIDTH;
1766
1767+ vht_capabilities_info = host_to_le32(hapd->iface->current_mode->vht_capab);
1768+ chwidth = hostapd_get_oper_chwidth(hapd->iconf);
1769+ if (vht_capabilities_info & VHT_CAP_EXTENDED_NSS_BW_SUPPORT
1770+ && ((chwidth == CHANWIDTH_160MHZ) || (chwidth == CHANWIDTH_80P80MHZ))) {
1771+ oper->operation_mode = host_to_le16(hapd->iconf->vht_oper_centr_freq_seg0_idx << 5);
1772+ }
1773+
1774 pos += sizeof(*oper);
1775
1776 return pos;
1777@@ -230,6 +239,9 @@ void hostapd_2040_coex_action(struct hostapd_data *hapd,
1778 return;
1779 }
1780
1781+ if (iface->conf->noscan || iface->conf->no_ht_coex)
1782+ return;
1783+
1784 if (len < IEEE80211_HDRLEN + 2 + sizeof(*bc_ie)) {
1785 wpa_printf(MSG_DEBUG,
1786 "Ignore too short 20/40 BSS Coexistence Management frame");
1787@@ -390,6 +402,9 @@ void ht40_intolerant_add(struct hostapd_iface *iface, struct sta_info *sta)
1788 if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G)
1789 return;
1790
1791+ if (iface->conf->noscan || iface->conf->no_ht_coex)
1792+ return;
1793+
1794 wpa_printf(MSG_INFO, "HT: Forty MHz Intolerant is set by STA " MACSTR
1795 " in Association Request", MAC2STR(sta->addr));
1796
1797diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c
1798index a5716f037..85790c7ed 100644
1799--- a/src/ap/ieee802_11_shared.c
1800+++ b/src/ap/ieee802_11_shared.c
1801@@ -1138,13 +1138,11 @@ u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len)
1802 u16 check_ext_capab(struct hostapd_data *hapd, struct sta_info *sta,
1803 const u8 *ext_capab_ie, size_t ext_capab_ie_len)
1804 {
1805-#ifdef CONFIG_INTERWORKING
1806 /* check for QoS Map support */
1807 if (ext_capab_ie_len >= 5) {
1808 if (ext_capab_ie[4] & 0x01)
1809 sta->qos_map_enabled = 1;
1810 }
1811-#endif /* CONFIG_INTERWORKING */
1812
1813 if (ext_capab_ie_len > 0) {
1814 sta->ecsa_supported = !!(ext_capab_ie[0] & BIT(2));
1815diff --git a/src/ap/ieee802_11_vht.c b/src/ap/ieee802_11_vht.c
1816index 4dc325ce8..68880ab64 100644
1817--- a/src/ap/ieee802_11_vht.c
1818+++ b/src/ap/ieee802_11_vht.c
1819@@ -26,6 +26,7 @@ u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid, u32 nsts)
1820 struct ieee80211_vht_capabilities *cap;
1821 struct hostapd_hw_modes *mode = hapd->iface->current_mode;
1822 u8 *pos = eid;
1823+ u8 chwidth;
1824
1825 if (!mode || is_6ghz_op_class(hapd->iconf->op_class))
1826 return eid;
1827@@ -63,6 +64,17 @@ u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid, u32 nsts)
1828 host_to_le32(nsts << VHT_CAP_BEAMFORMEE_STS_OFFSET);
1829 }
1830
1831+ chwidth = hostapd_get_oper_chwidth(hapd->iconf);
1832+ if (((host_to_le32(mode->vht_capab)) & VHT_CAP_EXTENDED_NSS_BW_SUPPORT)
1833+ && ((chwidth == CHANWIDTH_160MHZ) || (chwidth == CHANWIDTH_80P80MHZ))) {
1834+ cap->vht_capabilities_info |= VHT_CAP_EXTENDED_NSS_BW_SUPPORT;
1835+ cap->vht_capabilities_info &= ~(host_to_le32(VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ));
1836+ cap->vht_capabilities_info &= ~(host_to_le32(VHT_CAP_SUPP_CHAN_WIDTH_160MHZ));
1837+ cap->vht_capabilities_info &= ~(host_to_le32(VHT_CAP_SUPP_CHAN_WIDTH_MASK));
1838+ } else {
1839+ cap->vht_capabilities_info &= ~VHT_CAP_EXTENDED_NSS_BW_SUPPORT_MASK;
1840+ }
1841+
1842 /* Supported MCS set comes from hw */
1843 os_memcpy(&cap->vht_supported_mcs_set, mode->vht_mcs_set, 8);
1844
1845@@ -75,6 +87,7 @@ u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid, u32 nsts)
1846 u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid)
1847 {
1848 struct ieee80211_vht_operation *oper;
1849+ le32 vht_capabilities_info;
1850 u8 *pos = eid;
1851 enum oper_chan_width oper_chwidth =
1852 hostapd_get_oper_chwidth(hapd->iconf);
1853@@ -110,6 +123,7 @@ u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid)
1854 oper->vht_op_info_chan_center_freq_seg1_idx = seg1;
1855
1856 oper->vht_op_info_chwidth = oper_chwidth;
1857+ vht_capabilities_info = host_to_le32(hapd->iface->current_mode->vht_capab);
1858 if (oper_chwidth == CONF_OPER_CHWIDTH_160MHZ) {
1859 /*
1860 * Convert 160 MHz channel width to new style as interop
1861@@ -123,6 +137,9 @@ u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid)
1862 oper->vht_op_info_chan_center_freq_seg0_idx -= 8;
1863 else
1864 oper->vht_op_info_chan_center_freq_seg0_idx += 8;
1865+
1866+ if (vht_capabilities_info & VHT_CAP_EXTENDED_NSS_BW_SUPPORT)
1867+ oper->vht_op_info_chan_center_freq_seg1_idx = 0;
1868 } else if (oper_chwidth == CONF_OPER_CHWIDTH_80P80MHZ) {
1869 /*
1870 * Convert 80+80 MHz channel width to new style as interop
1871diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
1872index 8e98b6521..8abebbf34 100644
1873--- a/src/ap/ieee802_1x.c
1874+++ b/src/ap/ieee802_1x.c
1875@@ -600,6 +600,10 @@ int add_common_radius_attr(struct hostapd_data *hapd,
1876 struct hostapd_radius_attr *attr;
1877 int len;
1878
1879+ if (hapd->conf->dynamic_own_ip_addr)
1880+ radius_client_get_local_addr(hapd->radius,
1881+ &hapd->conf->own_ip_addr);
1882+
1883 if (!hostapd_config_get_radius_attr(req_attr,
1884 RADIUS_ATTR_NAS_IP_ADDRESS) &&
1885 hapd->conf->own_ip_addr.af == AF_INET &&
1886@@ -2845,6 +2849,7 @@ static const char * bool_txt(bool val)
1887 return val ? "TRUE" : "FALSE";
1888 }
1889
1890+#ifdef CONFIG_CTRL_IFACE_MIB
1891
1892 int ieee802_1x_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen)
1893 {
1894@@ -3031,6 +3036,7 @@ int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
1895 return len;
1896 }
1897
1898+#endif
1899
1900 #ifdef CONFIG_HS20
1901 static void ieee802_1x_wnm_notif_send(void *eloop_ctx, void *timeout_ctx)
1902diff --git a/src/ap/ndisc_snoop.c b/src/ap/ndisc_snoop.c
1903index 788c12fdc..bc1eb6251 100644
1904--- a/src/ap/ndisc_snoop.c
1905+++ b/src/ap/ndisc_snoop.c
1906@@ -61,6 +61,7 @@ void sta_ip6addr_del(struct hostapd_data *hapd, struct sta_info *sta)
1907 dl_list_for_each_safe(ip6addr, prev, &sta->ip6addr, struct ip6addr,
1908 list) {
1909 hostapd_drv_br_delete_ip_neigh(hapd, 6, (u8 *) &ip6addr->addr);
1910+ dl_list_del(&ip6addr->list);
1911 os_free(ip6addr);
1912 }
1913 }
1914diff --git a/src/ap/rrm.c b/src/ap/rrm.c
1915index f2d5cd16e..8220590a0 100644
1916--- a/src/ap/rrm.c
1917+++ b/src/ap/rrm.c
1918@@ -89,6 +89,9 @@ static void hostapd_handle_beacon_report(struct hostapd_data *hapd,
1919 return;
1920 wpa_msg(hapd->msg_ctx, MSG_INFO, BEACON_RESP_RX MACSTR " %u %02x %s",
1921 MAC2STR(addr), token, rep_mode, report);
1922+ if (len < sizeof(struct rrm_measurement_beacon_report))
1923+ return;
1924+ hostapd_ubus_notify_beacon_report(hapd, addr, token, rep_mode, (struct rrm_measurement_beacon_report*) pos, len);
1925 }
1926
1927
1928@@ -269,6 +272,8 @@ static void hostapd_send_nei_report_resp(struct hostapd_data *hapd,
1929 }
1930 }
1931
1932+ hapd->openwrt_stats.rrm.neighbor_report_tx++;
1933+
1934 hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
1935 wpabuf_head(buf), wpabuf_len(buf));
1936 wpabuf_free(buf);
1937@@ -350,6 +355,9 @@ void hostapd_handle_radio_measurement(struct hostapd_data *hapd,
1938 mgmt->u.action.u.rrm.action, MAC2STR(mgmt->sa));
1939
1940 switch (mgmt->u.action.u.rrm.action) {
1941+ case WLAN_RRM_LINK_MEASUREMENT_REPORT:
1942+ hostapd_ubus_handle_link_measurement(hapd, buf, len);
1943+ break;
1944 case WLAN_RRM_RADIO_MEASUREMENT_REPORT:
1945 hostapd_handle_radio_msmt_report(hapd, buf, len);
1946 break;
1947diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
1948index d483aa9d3..ee6e20538 100644
1949--- a/src/ap/sta_info.c
1950+++ b/src/ap/sta_info.c
1951@@ -539,6 +539,7 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
1952 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1953 HOSTAPD_LEVEL_INFO, "deauthenticated due to "
1954 "local deauth request");
1955+ hostapd_ubus_notify(hapd, "local-deauth", sta->addr);
1956 ap_free_sta(hapd, sta);
1957 return;
1958 }
1959@@ -694,6 +695,7 @@ skip_poll:
1960 mlme_deauthenticate_indication(
1961 hapd, sta,
1962 WLAN_REASON_PREV_AUTH_NOT_VALID);
1963+ hostapd_ubus_notify(hapd, "inactive-deauth", sta->addr);
1964 ap_free_sta(hapd, sta);
1965 break;
1966 }
1967@@ -1476,9 +1478,6 @@ bool ap_sta_set_authorized_flag(struct hostapd_data *hapd, struct sta_info *sta,
1968 mld_assoc_link_id = -2;
1969 }
1970 #endif /* CONFIG_IEEE80211BE */
1971- if (mld_assoc_link_id != -2)
1972- hostapd_prune_associations(hapd, sta->addr,
1973- mld_assoc_link_id);
1974 sta->flags |= WLAN_STA_AUTHORIZED;
1975 } else {
1976 sta->flags &= ~WLAN_STA_AUTHORIZED;
1977@@ -1515,15 +1514,28 @@ void ap_sta_set_authorized_event(struct hostapd_data *hapd,
1978 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(sta->addr));
1979
1980 if (authorized) {
1981+ static const char * const auth_algs[] = {
1982+ [WLAN_AUTH_OPEN] = "open",
1983+ [WLAN_AUTH_SHARED_KEY] = "shared",
1984+ [WLAN_AUTH_FT] = "ft",
1985+ [WLAN_AUTH_SAE] = "sae",
1986+ [WLAN_AUTH_FILS_SK] = "fils-sk",
1987+ [WLAN_AUTH_FILS_SK_PFS] = "fils-sk-pfs",
1988+ [WLAN_AUTH_FILS_PK] = "fils-pk",
1989+ [WLAN_AUTH_PASN] = "pasn",
1990+ };
1991+ const char *auth_alg = NULL;
1992 const u8 *dpp_pkhash;
1993 const char *keyid;
1994 char dpp_pkhash_buf[100];
1995 char keyid_buf[100];
1996 char ip_addr[100];
1997+ char alg_buf[100];
1998
1999 dpp_pkhash_buf[0] = '\0';
2000 keyid_buf[0] = '\0';
2001 ip_addr[0] = '\0';
2002+ alg_buf[0] = '\0';
2003 #ifdef CONFIG_P2P
2004 if (wpa_auth_get_ip_addr(sta->wpa_sm, ip_addr_buf) == 0) {
2005 os_snprintf(ip_addr, sizeof(ip_addr),
2006@@ -1534,6 +1546,13 @@ void ap_sta_set_authorized_event(struct hostapd_data *hapd,
2007 }
2008 #endif /* CONFIG_P2P */
2009
2010+ if (sta->auth_alg < ARRAY_SIZE(auth_algs))
2011+ auth_alg = auth_algs[sta->auth_alg];
2012+
2013+ if (auth_alg)
2014+ os_snprintf(alg_buf, sizeof(alg_buf),
2015+ " auth_alg=%s", auth_alg);
2016+
2017 keyid = ap_sta_wpa_get_keyid(hapd, sta);
2018 if (keyid) {
2019 os_snprintf(keyid_buf, sizeof(keyid_buf),
2020@@ -1552,17 +1571,19 @@ void ap_sta_set_authorized_event(struct hostapd_data *hapd,
2021 dpp_pkhash, SHA256_MAC_LEN);
2022 }
2023
2024- wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s%s%s",
2025- buf, ip_addr, keyid_buf, dpp_pkhash_buf);
2026+ hostapd_ubus_notify_authorized(hapd, sta, auth_alg);
2027+ wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s%s%s%s",
2028+ buf, ip_addr, keyid_buf, dpp_pkhash_buf, alg_buf);
2029
2030 if (hapd->msg_ctx_parent &&
2031 hapd->msg_ctx_parent != hapd->msg_ctx)
2032 wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO,
2033- AP_STA_CONNECTED "%s%s%s%s",
2034+ AP_STA_CONNECTED "%s%s%s%s%s",
2035 buf, ip_addr, keyid_buf,
2036- dpp_pkhash_buf);
2037+ dpp_pkhash_buf, alg_buf);
2038 } else {
2039 wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED "%s", buf);
2040+ hostapd_ubus_notify(hapd, "disassoc", sta->addr);
2041
2042 if (hapd->msg_ctx_parent &&
2043 hapd->msg_ctx_parent != hapd->msg_ctx)
2044diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
2045index 153e4a000..38b80903d 100644
2046--- a/src/ap/sta_info.h
2047+++ b/src/ap/sta_info.h
2048@@ -17,7 +17,6 @@
2049 #include "common/sae.h"
2050 #include "crypto/sha384.h"
2051 #include "pasn/pasn_common.h"
2052-#include "hostapd.h"
2053
2054 /* STA flags */
2055 #define WLAN_STA_AUTH BIT(0)
2056@@ -323,6 +322,7 @@ struct sta_info {
2057 #endif /* CONFIG_TESTING_OPTIONS */
2058 #ifdef CONFIG_AIRTIME_POLICY
2059 unsigned int airtime_weight;
2060+ unsigned int dyn_airtime_weight;
2061 struct os_reltime backlogged_until;
2062 #endif /* CONFIG_AIRTIME_POLICY */
2063
2064@@ -420,16 +420,6 @@ int ap_sta_re_add(struct hostapd_data *hapd, struct sta_info *sta);
2065
2066 void ap_free_sta_pasn(struct hostapd_data *hapd, struct sta_info *sta);
2067
2068-static inline bool ap_sta_is_mld(struct hostapd_data *hapd,
2069- struct sta_info *sta)
2070-{
2071-#ifdef CONFIG_IEEE80211BE
2072- return hapd->conf->mld_ap && sta && sta->mld_info.mld_sta;
2073-#else /* CONFIG_IEEE80211BE */
2074- return false;
2075-#endif /* CONFIG_IEEE80211BE */
2076-}
2077-
2078 static inline void ap_sta_set_mld(struct sta_info *sta, bool mld)
2079 {
2080 #ifdef CONFIG_IEEE80211BE
2081diff --git a/src/ap/vlan_full.c b/src/ap/vlan_full.c
2082index 19aa3c649..053d6338e 100644
2083--- a/src/ap/vlan_full.c
2084+++ b/src/ap/vlan_full.c
2085@@ -475,6 +475,9 @@ void vlan_newlink(const char *ifname, struct hostapd_data *hapd)
2086 if (!vlan)
2087 return;
2088
2089+ if (hapd->conf->ssid.vlan_no_bridge)
2090+ goto out;
2091+
2092 vlan->configured = 1;
2093
2094 notempty = vlan->vlan_desc.notempty;
2095@@ -506,6 +509,7 @@ void vlan_newlink(const char *ifname, struct hostapd_data *hapd)
2096 ifname, br_name, tagged[i], hapd);
2097 }
2098
2099+out:
2100 ifconfig_up(ifname);
2101 }
2102
2103diff --git a/src/ap/vlan_init.c b/src/ap/vlan_init.c
2104index 53eacfb45..b69f3de41 100644
2105--- a/src/ap/vlan_init.c
2106+++ b/src/ap/vlan_init.c
2107@@ -22,6 +22,7 @@
2108 static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
2109 int existsok)
2110 {
2111+ bool vlan_exists = iface_exists(vlan->ifname);
2112 int ret;
2113 #ifdef CONFIG_WEP
2114 int i;
2115@@ -36,7 +37,7 @@ static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
2116 }
2117 #endif /* CONFIG_WEP */
2118
2119- if (!iface_exists(vlan->ifname))
2120+ if (!vlan_exists)
2121 ret = hostapd_vlan_if_add(hapd, vlan->ifname);
2122 else if (!existsok)
2123 return -1;
2124@@ -51,6 +52,9 @@ static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
2125 if (hapd->wpa_auth)
2126 ret = wpa_auth_ensure_group(hapd->wpa_auth, vlan->vlan_id);
2127
2128+ if (!ret && !vlan_exists)
2129+ hostapd_ubus_add_vlan(hapd, vlan);
2130+
2131 if (ret == 0)
2132 return ret;
2133
2134@@ -77,6 +81,8 @@ int vlan_if_remove(struct hostapd_data *hapd, struct hostapd_vlan *vlan)
2135 "WPA deinitialization for VLAN %d failed (%d)",
2136 vlan->vlan_id, ret);
2137
2138+ hostapd_ubus_remove_vlan(hapd, vlan);
2139+
2140 return hostapd_vlan_if_remove(hapd, vlan->ifname);
2141 }
2142
2143diff --git a/src/ap/wnm_ap.c b/src/ap/wnm_ap.c
2144index af8cccaef..d259200c9 100644
2145--- a/src/ap/wnm_ap.c
2146+++ b/src/ap/wnm_ap.c
2147@@ -410,6 +410,7 @@ static int ieee802_11_send_bss_trans_mgmt_request(struct hostapd_data *hapd,
2148 mgmt->u.action.u.bss_tm_req.validity_interval = 1;
2149 pos = mgmt->u.action.u.bss_tm_req.variable;
2150
2151+ hapd->openwrt_stats.wnm.bss_transition_request_tx++;
2152 wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Request to "
2153 MACSTR " dialog_token=%u req_mode=0x%x disassoc_timer=%u "
2154 "validity_interval=%u",
2155@@ -478,7 +479,8 @@ static void ieee802_11_rx_bss_trans_mgmt_query(struct hostapd_data *hapd,
2156 MAC2STR(addr), reason, hex ? " neighbor=" : "", hex);
2157 os_free(hex);
2158
2159- ieee802_11_send_bss_trans_mgmt_request(hapd, addr, dialog_token);
2160+ if (!hostapd_ubus_notify_bss_transition_query(hapd, addr, dialog_token, reason, pos, end - pos))
2161+ ieee802_11_send_bss_trans_mgmt_request(hapd, addr, dialog_token);
2162 }
2163
2164
2165@@ -500,7 +502,7 @@ static void ieee802_11_rx_bss_trans_mgmt_resp(struct hostapd_data *hapd,
2166 size_t len)
2167 {
2168 u8 dialog_token, status_code, bss_termination_delay;
2169- const u8 *pos, *end;
2170+ const u8 *pos, *end, *target_bssid = NULL;
2171 int enabled = hapd->conf->bss_transition;
2172 struct sta_info *sta;
2173
2174@@ -547,6 +549,7 @@ static void ieee802_11_rx_bss_trans_mgmt_resp(struct hostapd_data *hapd,
2175 wpa_printf(MSG_DEBUG, "WNM: not enough room for Target BSSID field");
2176 return;
2177 }
2178+ target_bssid = pos;
2179 sta->agreed_to_steer = 1;
2180 eloop_cancel_timeout(ap_sta_reset_steer_flag_timer, hapd, sta);
2181 eloop_register_timeout(2, 0, ap_sta_reset_steer_flag_timer,
2182@@ -566,6 +569,10 @@ static void ieee802_11_rx_bss_trans_mgmt_resp(struct hostapd_data *hapd,
2183 MAC2STR(addr), status_code, bss_termination_delay);
2184 }
2185
2186+ hostapd_ubus_notify_bss_transition_response(hapd, sta->addr, dialog_token,
2187+ status_code, bss_termination_delay,
2188+ target_bssid, pos, end - pos);
2189+
2190 wpa_hexdump(MSG_DEBUG, "WNM: BSS Transition Candidate List Entries",
2191 pos, end - pos);
2192 }
2193@@ -814,10 +821,12 @@ int ieee802_11_rx_wnm_action_ap(struct hostapd_data *hapd,
2194 plen);
2195 return 0;
2196 case WNM_BSS_TRANS_MGMT_QUERY:
2197+ hapd->openwrt_stats.wnm.bss_transition_query_rx++;
2198 ieee802_11_rx_bss_trans_mgmt_query(hapd, mgmt->sa, payload,
2199 plen);
2200 return 0;
2201 case WNM_BSS_TRANS_MGMT_RESP:
2202+ hapd->openwrt_stats.wnm.bss_transition_response_rx++;
2203 ieee802_11_rx_bss_trans_mgmt_resp(hapd, mgmt->sa, payload,
2204 plen);
2205 return 0;
2206@@ -865,6 +874,7 @@ int wnm_send_disassoc_imminent(struct hostapd_data *hapd,
2207
2208 pos = mgmt->u.action.u.bss_tm_req.variable;
2209
2210+ hapd->openwrt_stats.wnm.bss_transition_request_tx++;
2211 wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Request frame to indicate imminent disassociation (disassoc_timer=%d) to "
2212 MACSTR, disassoc_timer, MAC2STR(sta->addr));
2213 if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0, NULL, 0, 0) < 0) {
2214@@ -947,6 +957,7 @@ int wnm_send_ess_disassoc_imminent(struct hostapd_data *hapd,
2215 return -1;
2216 }
2217
2218+ hapd->openwrt_stats.wnm.bss_transition_request_tx++;
2219 if (disassoc_timer) {
2220 /* send disassociation frame after time-out */
2221 set_disassoc_timer(hapd, sta, disassoc_timer);
2222@@ -1028,6 +1039,7 @@ int wnm_send_bss_tm_req(struct hostapd_data *hapd, struct sta_info *sta,
2223 }
2224 os_free(buf);
2225
2226+ hapd->openwrt_stats.wnm.bss_transition_request_tx++;
2227 if (disassoc_timer) {
2228 #ifdef CONFIG_IEEE80211BE
2229 if (ap_sta_is_mld(hapd, sta)) {
2230diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
2231index 7a07dcc4c..b23d75444 100644
2232--- a/src/ap/wpa_auth.c
2233+++ b/src/ap/wpa_auth.c
2234@@ -5865,6 +5865,7 @@ static const char * wpa_bool_txt(int val)
2235 return val ? "TRUE" : "FALSE";
2236 }
2237
2238+#ifdef CONFIG_CTRL_IFACE_MIB
2239
2240 #define RSN_SUITE "%02x-%02x-%02x-%d"
2241 #define RSN_SUITE_ARG(s) \
2242@@ -6017,7 +6018,7 @@ int wpa_get_mib_sta(struct wpa_state_machine *sm, char *buf, size_t buflen)
2243
2244 return len;
2245 }
2246-
2247+#endif
2248
2249 void wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth)
2250 {
2251diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
2252index 1726c7201..5a9ec6975 100644
2253--- a/src/ap/wpa_auth_glue.c
2254+++ b/src/ap/wpa_auth_glue.c
2255@@ -275,6 +275,7 @@ static void hostapd_wpa_auth_psk_failure_report(void *ctx, const u8 *addr)
2256 struct hostapd_data *hapd = ctx;
2257 wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_POSSIBLE_PSK_MISMATCH MACSTR,
2258 MAC2STR(addr));
2259+ hostapd_ubus_notify(hapd, "key-mismatch", addr);
2260 }
2261
2262
2263@@ -1812,8 +1813,12 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
2264 wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt)) {
2265 const char *ft_iface;
2266
2267- ft_iface = hapd->conf->bridge[0] ? hapd->conf->bridge :
2268- hapd->conf->iface;
2269+ if (hapd->conf->ft_iface[0])
2270+ ft_iface = hapd->conf->ft_iface;
2271+ else if (hapd->conf->bridge[0])
2272+ ft_iface = hapd->conf->bridge;
2273+ else
2274+ ft_iface = hapd->conf->iface;
2275 hapd->l2 = l2_packet_init(ft_iface, NULL, ETH_P_RRB,
2276 hostapd_rrb_receive, hapd, 1);
2277 if (!hapd->l2) {
2278diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c
2279index 82d4d5fdd..dfc5c3ecb 100644
2280--- a/src/ap/wps_hostapd.c
2281+++ b/src/ap/wps_hostapd.c
2282@@ -394,9 +394,8 @@ static int hapd_wps_reconfig_in_memory(struct hostapd_data *hapd,
2283 bss->wpa_pairwise |= WPA_CIPHER_GCMP;
2284 else
2285 bss->wpa_pairwise |= WPA_CIPHER_CCMP;
2286- }
2287 #ifndef CONFIG_NO_TKIP
2288- if (cred->encr_type & WPS_ENCR_TKIP)
2289+ } else if (cred->encr_type & WPS_ENCR_TKIP)
2290 bss->wpa_pairwise |= WPA_CIPHER_TKIP;
2291 #endif /* CONFIG_NO_TKIP */
2292 bss->rsn_pairwise = bss->wpa_pairwise;
2293@@ -1181,8 +1180,7 @@ int hostapd_init_wps(struct hostapd_data *hapd,
2294 WPA_CIPHER_GCMP_256)) {
2295 wps->encr_types |= WPS_ENCR_AES;
2296 wps->encr_types_rsn |= WPS_ENCR_AES;
2297- }
2298- if (conf->rsn_pairwise & WPA_CIPHER_TKIP) {
2299+ } else if (conf->rsn_pairwise & WPA_CIPHER_TKIP) {
2300 #ifdef CONFIG_NO_TKIP
2301 wpa_printf(MSG_INFO, "WPS: TKIP not supported");
2302 goto fail;
2303diff --git a/src/ap/x_snoop.c b/src/ap/x_snoop.c
2304index 029f4de23..4c20f137f 100644
2305--- a/src/ap/x_snoop.c
2306+++ b/src/ap/x_snoop.c
2307@@ -33,28 +33,31 @@ int x_snoop_init(struct hostapd_data *hapd)
2308
2309 hapd->x_snoop_initialized = true;
2310
2311- if (hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_HAIRPIN_MODE,
2312+ if (!conf->snoop_iface[0] &&
2313+ hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_HAIRPIN_MODE,
2314 1)) {
2315 wpa_printf(MSG_DEBUG,
2316 "x_snoop: Failed to enable hairpin_mode on the bridge port");
2317 return -1;
2318 }
2319
2320- if (hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_PROXYARP, 1)) {
2321+ if (!conf->snoop_iface[0] &&
2322+ hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_PROXYARP, 1)) {
2323 wpa_printf(MSG_DEBUG,
2324 "x_snoop: Failed to enable proxyarp on the bridge port");
2325 return -1;
2326 }
2327
2328 if (hostapd_drv_br_set_net_param(hapd, DRV_BR_NET_PARAM_GARP_ACCEPT,
2329- 1)) {
2330+ conf->snoop_iface[0] ? conf->snoop_iface : NULL, 1)) {
2331 wpa_printf(MSG_DEBUG,
2332 "x_snoop: Failed to enable accepting gratuitous ARP on the bridge");
2333 return -1;
2334 }
2335
2336 #ifdef CONFIG_IPV6
2337- if (hostapd_drv_br_set_net_param(hapd, DRV_BR_MULTICAST_SNOOPING, 1)) {
2338+ if (!conf->snoop_iface[0] &&
2339+ hostapd_drv_br_set_net_param(hapd, DRV_BR_MULTICAST_SNOOPING, NULL, 1)) {
2340 wpa_printf(MSG_DEBUG,
2341 "x_snoop: Failed to enable multicast snooping on the bridge");
2342 return -1;
2343@@ -73,8 +76,12 @@ x_snoop_get_l2_packet(struct hostapd_data *hapd,
2344 {
2345 struct hostapd_bss_config *conf = hapd->conf;
2346 struct l2_packet_data *l2;
2347+ const char *ifname = conf->bridge;
2348+
2349+ if (conf->snoop_iface[0])
2350+ ifname = conf->snoop_iface;
2351
2352- l2 = l2_packet_init(conf->bridge, NULL, ETH_P_ALL, handler, hapd, 1);
2353+ l2 = l2_packet_init(ifname, NULL, ETH_P_ALL, handler, hapd, 1);
2354 if (l2 == NULL) {
2355 wpa_printf(MSG_DEBUG,
2356 "x_snoop: Failed to initialize L2 packet processing %s",
2357@@ -127,9 +134,12 @@ void x_snoop_mcast_to_ucast_convert_send(struct hostapd_data *hapd,
2358
2359 void x_snoop_deinit(struct hostapd_data *hapd)
2360 {
2361+ struct hostapd_bss_config *conf = hapd->conf;
2362+
2363 if (!hapd->x_snoop_initialized)
2364 return;
2365- hostapd_drv_br_set_net_param(hapd, DRV_BR_NET_PARAM_GARP_ACCEPT, 0);
2366+ hostapd_drv_br_set_net_param(hapd, DRV_BR_NET_PARAM_GARP_ACCEPT,
2367+ conf->snoop_iface[0] ? conf->snoop_iface : NULL, 0);
2368 hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_PROXYARP, 0);
2369 hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_HAIRPIN_MODE, 0);
2370 hapd->x_snoop_initialized = false;
2371diff --git a/src/common/dpp_crypto.c b/src/common/dpp_crypto.c
2372index f17f95a2c..39d39f429 100644
2373--- a/src/common/dpp_crypto.c
2374+++ b/src/common/dpp_crypto.c
2375@@ -269,6 +269,12 @@ int dpp_get_pubkey_hash(struct crypto_ec_key *key, u8 *hash)
2376
2377 struct crypto_ec_key * dpp_gen_keypair(const struct dpp_curve_params *curve)
2378 {
2379+ if (curve == NULL) {
2380+ wpa_printf(MSG_DEBUG,
2381+ "DPP: %s curve must be initialized", __func__);
2382+ return NULL;
2383+ }
2384+
2385 struct crypto_ec_key *key;
2386
2387 wpa_printf(MSG_DEBUG, "DPP: Generating a keypair");
2388@@ -1582,7 +1588,9 @@ dpp_pkex_derive_Qr(const struct dpp_curve_params *curve, const u8 *mac_resp,
2389 Pr = crypto_ec_key_get_public_key(Pr_key);
2390 Qr = crypto_ec_point_init(ec);
2391 hash_bn = crypto_bignum_init_set(hash, curve->hash_len);
2392- if (!Pr || !Qr || !hash_bn || crypto_ec_point_mul(ec, Pr, hash_bn, Qr))
2393+ if (!Pr || !Qr || !hash_bn ||
2394+ crypto_bignum_mod(hash_bn, crypto_ec_get_prime(ec), hash_bn) ||
2395+ crypto_ec_point_mul(ec, Pr, hash_bn, Qr))
2396 goto fail;
2397
2398 if (crypto_ec_point_is_at_infinity(ec, Qr)) {
2399diff --git a/src/common/hw_features_common.c b/src/common/hw_features_common.c
2400index 2c47bf812..8bd6e994d 100644
2401--- a/src/common/hw_features_common.c
2402+++ b/src/common/hw_features_common.c
2403@@ -898,6 +898,7 @@ int ieee80211ac_cap_check(u32 hw, u32 conf)
2404 VHT_CAP_CHECK(VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB);
2405 VHT_CAP_CHECK(VHT_CAP_RX_ANTENNA_PATTERN);
2406 VHT_CAP_CHECK(VHT_CAP_TX_ANTENNA_PATTERN);
2407+ VHT_CAP_CHECK(VHT_CAP_EXTENDED_NSS_BW_SUPPORT);
2408
2409 #undef VHT_CAP_CHECK
2410 #undef VHT_CAP_CHECK_MAX
2411diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
2412index 5b39a61e1..7a1da3252 100644
2413--- a/src/common/ieee802_11_defs.h
2414+++ b/src/common/ieee802_11_defs.h
2415@@ -1397,6 +1397,8 @@ struct ieee80211_ampe_ie {
2416 #define VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB ((u32) BIT(26) | BIT(27))
2417 #define VHT_CAP_RX_ANTENNA_PATTERN ((u32) BIT(28))
2418 #define VHT_CAP_TX_ANTENNA_PATTERN ((u32) BIT(29))
2419+#define VHT_CAP_EXTENDED_NSS_BW_SUPPORT ((u32) BIT(30))
2420+#define VHT_CAP_EXTENDED_NSS_BW_SUPPORT_MASK ((u32) BIT(30) | BIT(31))
2421
2422 #define VHT_OPMODE_CHANNEL_WIDTH_MASK ((u8) BIT(0) | BIT(1))
2423 #define VHT_OPMODE_CHANNEL_RxNSS_MASK ((u8) BIT(4) | BIT(5) | \
2424diff --git a/src/common/sae.c b/src/common/sae.c
2425index f1c164e13..05de737e5 100644
2426--- a/src/common/sae.c
2427+++ b/src/common/sae.c
2428@@ -1278,6 +1278,13 @@ void sae_deinit_pt(struct sae_pt *pt)
2429 static int sae_derive_commit_element_ecc(struct sae_data *sae,
2430 struct crypto_bignum *mask)
2431 {
2432+ if (sae->tmp->pwe_ecc == NULL) {
2433+ wpa_printf(MSG_DEBUG,
2434+ "SAE: %s sae->tmp->pwe_ecc must be initialized",
2435+ __func__);
2436+ return -1;
2437+ }
2438+
2439 /* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */
2440 if (!sae->tmp->own_commit_element_ecc) {
2441 sae->tmp->own_commit_element_ecc =
2442diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c
2443index 6ea3311ce..7a608c30e 100644
2444--- a/src/common/wpa_common.c
2445+++ b/src/common/wpa_common.c
2446@@ -2856,6 +2856,31 @@ u32 wpa_akm_to_suite(int akm)
2447 }
2448
2449
2450+static void wpa_fixup_wpa_ie_rsn(u8 *assoc_ie, const u8 *wpa_msg_ie,
2451+ size_t rsn_ie_len)
2452+{
2453+ int pos, count;
2454+
2455+ pos = sizeof(struct rsn_ie_hdr) + RSN_SELECTOR_LEN;
2456+ if (rsn_ie_len < pos + 2)
2457+ return;
2458+
2459+ count = WPA_GET_LE16(wpa_msg_ie + pos);
2460+ pos += 2 + count * RSN_SELECTOR_LEN;
2461+ if (rsn_ie_len < pos + 2)
2462+ return;
2463+
2464+ count = WPA_GET_LE16(wpa_msg_ie + pos);
2465+ pos += 2 + count * RSN_SELECTOR_LEN;
2466+ if (rsn_ie_len < pos + 2)
2467+ return;
2468+
2469+ if (!assoc_ie[pos] && !assoc_ie[pos + 1] &&
2470+ (wpa_msg_ie[pos] || wpa_msg_ie[pos + 1]))
2471+ memcpy(&assoc_ie[pos], &wpa_msg_ie[pos], 2);
2472+}
2473+
2474+
2475 int wpa_compare_rsn_ie(int ft_initial_assoc,
2476 const u8 *ie1, size_t ie1len,
2477 const u8 *ie2, size_t ie2len)
2478@@ -2863,8 +2888,19 @@ int wpa_compare_rsn_ie(int ft_initial_assoc,
2479 if (ie1 == NULL || ie2 == NULL)
2480 return -1;
2481
2482- if (ie1len == ie2len && os_memcmp(ie1, ie2, ie1len) == 0)
2483- return 0; /* identical IEs */
2484+ if (ie1len == ie2len) {
2485+ u8 *ie_tmp;
2486+
2487+ if (os_memcmp(ie1, ie2, ie1len) == 0)
2488+ return 0; /* identical IEs */
2489+
2490+ ie_tmp = alloca(ie1len);
2491+ memcpy(ie_tmp, ie1, ie1len);
2492+ wpa_fixup_wpa_ie_rsn(ie_tmp, ie2, ie1len);
2493+
2494+ if (os_memcmp(ie_tmp, ie2, ie1len) == 0)
2495+ return 0; /* only mismatch in RSN capabilties */
2496+ }
2497
2498 #ifdef CONFIG_IEEE80211R
2499 if (ft_initial_assoc) {
2500diff --git a/src/common/wpa_ctrl.c b/src/common/wpa_ctrl.c
2501index 7e197f094..791fdbf93 100644
2502--- a/src/common/wpa_ctrl.c
2503+++ b/src/common/wpa_ctrl.c
2504@@ -135,7 +135,7 @@ try_again:
2505 return NULL;
2506 }
2507 tries++;
2508-#ifdef ANDROID
2509+
2510 /* Set client socket file permissions so that bind() creates the client
2511 * socket with these permissions and there is no need to try to change
2512 * them with chmod() after bind() which would have potential issues with
2513@@ -147,7 +147,7 @@ try_again:
2514 * operations to allow the response to go through. Those are using the
2515 * no-deference-symlinks version to avoid races. */
2516 fchmod(ctrl->s, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
2517-#endif /* ANDROID */
2518+
2519 if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
2520 sizeof(ctrl->local)) < 0) {
2521 if (errno == EADDRINUSE && tries < 2) {
2522@@ -165,7 +165,11 @@ try_again:
2523 return NULL;
2524 }
2525
2526-#ifdef ANDROID
2527+#ifndef ANDROID
2528+ /* Set group even if we do not have privileges to change owner */
2529+ lchown(ctrl->local.sun_path, -1, 101);
2530+ lchown(ctrl->local.sun_path, 101, 101);
2531+#else
2532 /* Set group even if we do not have privileges to change owner */
2533 lchown(ctrl->local.sun_path, -1, AID_WIFI);
2534 lchown(ctrl->local.sun_path, AID_SYSTEM, AID_WIFI);
2535diff --git a/src/crypto/Makefile b/src/crypto/Makefile
2536index ce0997091..96bac9476 100644
2537--- a/src/crypto/Makefile
2538+++ b/src/crypto/Makefile
2539@@ -1,10 +1,121 @@
2540-CFLAGS += -DCONFIG_CRYPTO_INTERNAL
2541-CFLAGS += -DCONFIG_TLS_INTERNAL_CLIENT
2542-CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER
2543 #CFLAGS += -DALL_DH_GROUPS
2544 CFLAGS += -DCONFIG_SHA256
2545 CFLAGS += -DCONFIG_SHA384
2546+CFLAGS += -DCONFIG_HMAC_SHA256_KDF
2547 CFLAGS += -DCONFIG_HMAC_SHA384_KDF
2548+
2549+# crypto_module_tests.c
2550+CFLAGS += -DCONFIG_MODULE_TESTS
2551+CFLAGS += -DCONFIG_DPP
2552+#CFLAGS += -DCONFIG_DPP2
2553+#CFLAGS += -DCONFIG_DPP3
2554+CFLAGS += -DCONFIG_ECC
2555+CFLAGS += -DCONFIG_MESH
2556+CFLAGS += -DEAP_PSK
2557+CFLAGS += -DEAP_FAST
2558+
2559+ifeq ($(CONFIG_TLS),mbedtls)
2560+
2561+# (enable features for 'cd tests; make run-tests CONFIG_TLS=mbedtls')
2562+CFLAGS += -DCRYPTO_RSA_OAEP_SHA256
2563+CFLAGS += -DCONFIG_DES
2564+CFLAGS += -DEAP_IKEV2
2565+CFLAGS += -DEAP_MSCHAPv2
2566+CFLAGS += -DEAP_SIM
2567+
2568+LIB_OBJS = tls_mbedtls.o crypto_mbedtls.o
2569+LIB_OBJS+= \
2570+ aes-eax.o \
2571+ aes-siv.o \
2572+ dh_groups.o \
2573+ milenage.o \
2574+ ms_funcs.o
2575+
2576+else
2577+ifeq ($(CONFIG_TLS),openssl)
2578+
2579+# (enable features for 'cd tests; make run-tests CONFIG_TLS=openssl')
2580+ifndef CONFIG_TLS_DEFAULT_CIPHERS
2581+CONFIG_TLS_DEFAULT_CIPHERS = "DEFAULT:!EXP:!LOW"
2582+endif
2583+CFLAGS += -DTLS_DEFAULT_CIPHERS=\"$(CONFIG_TLS_DEFAULT_CIPHERS)\"
2584+CFLAGS += -DCRYPTO_RSA_OAEP_SHA256
2585+CFLAGS += -DEAP_TLS_OPENSSL
2586+
2587+LIB_OBJS = tls_openssl.o fips_prf_openssl.o crypto_openssl.o
2588+LIB_OBJS+= \
2589+ aes-ctr.o \
2590+ aes-eax.o \
2591+ aes-encblock.o \
2592+ aes-siv.o \
2593+ dh_groups.o \
2594+ milenage.o \
2595+ ms_funcs.o \
2596+ sha1-prf.o \
2597+ sha1-tlsprf.o \
2598+ sha1-tprf.o \
2599+ sha256-kdf.o \
2600+ sha256-prf.o \
2601+ sha256-tlsprf.o
2602+
2603+else
2604+ifeq ($(CONFIG_TLS),wolfssl)
2605+
2606+# (wolfssl libraries must be built with ./configure --enable-wpas)
2607+# (enable features for 'cd tests; make run-tests CONFIG_TLS=wolfssl')
2608+CFLAGS += -DWOLFSSL_DER_LOAD
2609+CFLAGS += -DCONFIG_DES
2610+
2611+LIB_OBJS = tls_wolfssl.o fips_prf_wolfssl.o crypto_wolfssl.o
2612+LIB_OBJS+= \
2613+ aes-ctr.o \
2614+ aes-eax.o \
2615+ aes-encblock.o \
2616+ aes-siv.o \
2617+ dh_groups.o \
2618+ milenage.o \
2619+ ms_funcs.o \
2620+ sha1-prf.o \
2621+ sha1-tlsprf.o \
2622+ sha1-tprf.o \
2623+ sha256-kdf.o \
2624+ sha256-prf.o \
2625+ sha256-tlsprf.o
2626+
2627+else
2628+ifeq ($(CONFIG_TLS),gnutls)
2629+
2630+# (enable features for 'cd tests; make run-tests CONFIG_TLS=gnutls')
2631+LIB_OBJS = tls_gnutls.o crypto_gnutls.o
2632+LIB_OBJS+= \
2633+ aes-cbc.o \
2634+ aes-ctr.o \
2635+ aes-eax.o \
2636+ aes-encblock.o \
2637+ aes-omac1.o \
2638+ aes-siv.o \
2639+ aes-unwrap.o \
2640+ aes-wrap.o \
2641+ dh_group5.o \
2642+ dh_groups.o \
2643+ milenage.o \
2644+ ms_funcs.o \
2645+ rc4.o \
2646+ sha1-pbkdf2.o \
2647+ sha1-prf.o \
2648+ fips_prf_internal.o \
2649+ sha1-internal.o \
2650+ sha1-tlsprf.o \
2651+ sha1-tprf.o \
2652+ sha256-kdf.o \
2653+ sha256-prf.o \
2654+ sha256-tlsprf.o
2655+
2656+else
2657+
2658+CFLAGS += -DCONFIG_CRYPTO_INTERNAL
2659+CFLAGS += -DCONFIG_TLS_INTERNAL_CLIENT
2660+CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER
2661 CFLAGS += -DCONFIG_INTERNAL_SHA384
2662
2663 LIB_OBJS= \
2664@@ -13,7 +124,6 @@ LIB_OBJS= \
2665 aes-ctr.o \
2666 aes-eax.o \
2667 aes-encblock.o \
2668- aes-gcm.o \
2669 aes-internal.o \
2670 aes-internal-dec.o \
2671 aes-internal-enc.o \
2672@@ -37,6 +147,7 @@ LIB_OBJS= \
2673 sha1-tlsprf.o \
2674 sha1-tprf.o \
2675 sha256.o \
2676+ sha256-kdf.o \
2677 sha256-prf.o \
2678 sha256-tlsprf.o \
2679 sha256-internal.o \
2680@@ -53,6 +164,16 @@ LIB_OBJS += crypto_internal-modexp.o
2681 LIB_OBJS += crypto_internal-rsa.o
2682 LIB_OBJS += tls_internal.o
2683 LIB_OBJS += fips_prf_internal.o
2684+
2685+endif
2686+endif
2687+endif
2688+endif
2689+
2690+
2691+# (used by wlantest/{bip,gcmp,rx_mgmt}.c and tests/test-aes.c)
2692+LIB_OBJS += aes-gcm.o
2693+
2694 ifndef TEST_FUZZ
2695 LIB_OBJS += random.o
2696 endif
2697diff --git a/src/crypto/crypto_mbedtls.c b/src/crypto/crypto_mbedtls.c
2698new file mode 100644
2699index 000000000..7a91c965f
2700--- /dev/null
2701+++ b/src/crypto/crypto_mbedtls.c
2702@@ -0,0 +1,4228 @@
2703+/*
2704+ * crypto wrapper functions for mbed TLS
2705+ *
2706+ * SPDX-FileCopyrightText: 2022 Glenn Strauss <gstrauss@gluelogic.com>
2707+ * SPDX-License-Identifier: BSD-3-Clause
2708+ */
2709+
2710+#include "utils/includes.h"
2711+#include "utils/common.h"
2712+
2713+#include <mbedtls/version.h>
2714+#include <mbedtls/entropy.h>
2715+#include <mbedtls/ctr_drbg.h>
2716+#include <mbedtls/platform_util.h> /* mbedtls_platform_zeroize() */
2717+#include <mbedtls/asn1.h>
2718+#include <mbedtls/asn1write.h>
2719+#include <mbedtls/aes.h>
2720+#include <mbedtls/md.h>
2721+#include <mbedtls/md5.h>
2722+#include <mbedtls/sha1.h>
2723+#include <mbedtls/sha256.h>
2724+#include <mbedtls/sha512.h>
2725+
2726+#ifndef MBEDTLS_PRIVATE
2727+#define MBEDTLS_PRIVATE(x) x
2728+#endif
2729+
2730+/* hostapd/wpa_supplicant provides forced_memzero(),
2731+ * but prefer mbedtls_platform_zeroize() */
2732+#define forced_memzero(ptr,sz) mbedtls_platform_zeroize(ptr,sz)
2733+
2734+#ifndef __has_attribute
2735+#define __has_attribute(x) 0
2736+#endif
2737+
2738+#ifndef __GNUC_PREREQ
2739+#define __GNUC_PREREQ(maj,min) 0
2740+#endif
2741+
2742+#ifndef __attribute_cold__
2743+#if __has_attribute(cold) \
2744+ || __GNUC_PREREQ(4,3)
2745+#define __attribute_cold__ __attribute__((__cold__))
2746+#else
2747+#define __attribute_cold__
2748+#endif
2749+#endif
2750+
2751+#ifndef __attribute_noinline__
2752+#if __has_attribute(noinline) \
2753+ || __GNUC_PREREQ(3,1)
2754+#define __attribute_noinline__ __attribute__((__noinline__))
2755+#else
2756+#define __attribute_noinline__
2757+#endif
2758+#endif
2759+
2760+#include "crypto.h"
2761+#include "aes_wrap.h"
2762+#include "aes.h"
2763+#include "md5.h"
2764+#include "sha1.h"
2765+#include "sha256.h"
2766+#include "sha384.h"
2767+#include "sha512.h"
2768+
2769+
2770+/*
2771+ * selective code inclusion based on preprocessor defines
2772+ *
2773+ * future: additional code could be wrapped with preprocessor checks if
2774+ * wpa_supplicant/Makefile and hostap/Makefile were more consistent with
2775+ * setting preprocessor defines for named groups of functionality
2776+ */
2777+
2778+#if defined(CONFIG_FIPS)
2779+#undef MBEDTLS_MD4_C /* omit md4_vector() */
2780+#undef MBEDTLS_MD5_C /* omit md5_vector() hmac_md5_vector() hmac_md5() */
2781+#undef MBEDTLS_DES_C /* omit des_encrypt() */
2782+#undef MBEDTLS_NIST_KW_C /* omit aes_wrap() aes_unwrap() */
2783+#define CRYPTO_MBEDTLS_CONFIG_FIPS
2784+#endif
2785+
2786+#if !defined(CONFIG_FIPS)
2787+#if defined(EAP_PWD) \
2788+ || defined(EAP_LEAP) || defined(EAP_LEAP_DYNAMIC) \
2789+ || defined(EAP_TTLS) || defined(EAP_TTLS_DYNAMIC) \
2790+ || defined(EAP_MSCHAPv2) || defined(EAP_MSCHAPv2_DYNAMIC) \
2791+ || defined(EAP_SERVER_MSCHAPV2)
2792+#ifndef MBEDTLS_MD4_C /* (MD4 not in mbedtls 3.x) */
2793+#include "md4-internal.c"/* pull in hostap local implementation */
2794+#endif /* md4_vector() */
2795+#else
2796+#undef MBEDTLS_MD4_C /* omit md4_vector() */
2797+#endif
2798+#endif
2799+
2800+#if !defined(CONFIG_NO_RC4) && !defined(CONFIG_NO_WPA)
2801+#ifndef MBEDTLS_ARC4_C /* (RC4 not in mbedtls 3.x) */
2802+#include "rc4.c" /* pull in hostap local implementation */
2803+#endif /* rc4_skip() */
2804+#else
2805+#undef MBEDTLS_ARC4_C /* omit rc4_skip() */
2806+#endif
2807+
2808+#if defined(CONFIG_MACSEC) \
2809+ || defined(CONFIG_NO_RADIUS) \
2810+ || defined(CONFIG_IEEE80211R) \
2811+ || defined(EAP_SERVER_FAST) \
2812+ || defined(EAP_SERVER_TEAP) \
2813+ || !defined(CONFIG_NO_WPA)
2814+ /* aes_wrap() aes_unwrap() */
2815+#else
2816+#undef MBEDTLS_NIST_KW_C /* omit aes_wrap() aes_unwrap() */
2817+#endif
2818+
2819+#if !defined(CONFIG_SHA256)
2820+#undef MBEDTLS_SHA256_C
2821+#endif
2822+
2823+#if !defined(CONFIG_SHA384) && !defined(CONFIG_SHA512)
2824+#undef MBEDTLS_SHA512_C
2825+#endif
2826+
2827+#if defined(CONFIG_HMAC_SHA256_KDF)
2828+#define CRYPTO_MBEDTLS_HMAC_KDF_SHA256
2829+#endif
2830+#if defined(CONFIG_HMAC_SHA384_KDF)
2831+#define CRYPTO_MBEDTLS_HMAC_KDF_SHA384
2832+#endif
2833+#if defined(CONFIG_HMAC_SHA512_KDF)
2834+#define CRYPTO_MBEDTLS_HMAC_KDF_SHA512
2835+#endif
2836+
2837+#if defined(EAP_SIM) || defined(EAP_SIM_DYNAMIC) || defined(EAP_SERVER_SIM) \
2838+ || defined(EAP_AKA) || defined(EAP_AKA_DYNAMIC) || defined(EAP_SERVER_AKA)
2839+/* EAP_SIM=y EAP_AKA=y */
2840+#define CRYPTO_MBEDTLS_FIPS186_2_PRF
2841+#endif
2842+
2843+#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) \
2844+ || defined(EAP_TEAP) || defined(EAP_TEAP_DYNAMIC) || defined(EAP_SERVER_FAST)
2845+#define CRYPTO_MBEDTLS_SHA1_T_PRF
2846+#endif
2847+
2848+#if defined(CONFIG_DES)
2849+#define CRYPTO_MBEDTLS_DES_ENCRYPT
2850+#endif /* des_encrypt() */
2851+
2852+#if !defined(CONFIG_NO_PBKDF2)
2853+#define CRYPTO_MBEDTLS_PBKDF2_SHA1
2854+#endif /* pbkdf2_sha1() */
2855+
2856+#if defined(EAP_IKEV2) \
2857+ || defined(EAP_IKEV2_DYNAMIC) \
2858+ || defined(EAP_SERVER_IKEV2) /* CONFIG_EAP_IKEV2=y */
2859+#define CRYPTO_MBEDTLS_CRYPTO_CIPHER
2860+#endif /* crypto_cipher_*() */
2861+
2862+#if defined(EAP_PWD) || defined(EAP_SERVER_PWD) /* CONFIG_EAP_PWD=y */
2863+#define CRYPTO_MBEDTLS_CRYPTO_HASH
2864+#endif /* crypto_hash_*() */
2865+
2866+#if defined(EAP_PWD) || defined(EAP_SERVER_PWD) /* CONFIG_EAP_PWD=y */ \
2867+ || defined(CONFIG_SAE) /* CONFIG_SAE=y */
2868+#define CRYPTO_MBEDTLS_CRYPTO_BIGNUM
2869+#endif /* crypto_bignum_*() */
2870+
2871+#if defined(EAP_PWD) /* CONFIG_EAP_PWD=y */ \
2872+ || defined(EAP_EKE) /* CONFIG_EAP_EKE=y */ \
2873+ || defined(EAP_EKE_DYNAMIC) /* CONFIG_EAP_EKE=y */ \
2874+ || defined(EAP_SERVER_EKE) /* CONFIG_EAP_EKE=y */ \
2875+ || defined(EAP_IKEV2) /* CONFIG_EAP_IKEV2y */ \
2876+ || defined(EAP_IKEV2_DYNAMIC)/* CONFIG_EAP_IKEV2=y */ \
2877+ || defined(EAP_SERVER_IKEV2) /* CONFIG_EAP_IKEV2=y */ \
2878+ || defined(CONFIG_SAE) /* CONFIG_SAE=y */ \
2879+ || defined(CONFIG_WPS) /* CONFIG_WPS=y */
2880+#define CRYPTO_MBEDTLS_CRYPTO_DH
2881+#if defined(CONFIG_WPS_NFC)
2882+#define CRYPTO_MBEDTLS_DH5_INIT_FIXED
2883+#endif /* dh5_init_fixed() */
2884+#endif /* crypto_dh_*() */
2885+
2886+#if !defined(CONFIG_NO_WPA) /* CONFIG_NO_WPA= */
2887+#define CRYPTO_MBEDTLS_CRYPTO_ECDH
2888+#endif /* crypto_ecdh_*() */
2889+
2890+#if defined(CONFIG_ECC)
2891+#define CRYPTO_MBEDTLS_CRYPTO_BIGNUM
2892+#define CRYPTO_MBEDTLS_CRYPTO_EC
2893+#endif /* crypto_ec_*() crypto_ec_key_*() */
2894+
2895+#if defined(CONFIG_DPP) /* CONFIG_DPP=y */
2896+#define CRYPTO_MBEDTLS_CRYPTO_EC_DPP /* extra for DPP */
2897+#define CRYPTO_MBEDTLS_CRYPTO_CSR
2898+#endif /* crypto_csr_*() */
2899+
2900+#if defined(CONFIG_DPP3) /* CONFIG_DPP3=y */
2901+#define CRYPTO_MBEDTLS_CRYPTO_HPKE
2902+#endif
2903+
2904+#if defined(CONFIG_DPP2) /* CONFIG_DPP2=y */
2905+#define CRYPTO_MBEDTLS_CRYPTO_PKCS7
2906+#endif /* crypto_pkcs7_*() */
2907+
2908+#if defined(EAP_SIM) || defined(EAP_SIM_DYNAMIC) || defined(EAP_SERVER_SIM) \
2909+ || defined(EAP_AKA) || defined(EAP_AKA_DYNAMIC) || defined(EAP_SERVER_AKA) \
2910+ || defined(CONFIG_AP) || defined(HOSTAPD)
2911+/* CONFIG_EAP_SIM=y CONFIG_EAP_AKA=y CONFIG_AP=y HOSTAPD */
2912+#if defined(CRYPTO_RSA_OAEP_SHA256)
2913+#define CRYPTO_MBEDTLS_CRYPTO_RSA
2914+#endif
2915+#endif /* crypto_rsa_*() */
2916+
2917+
2918+static int ctr_drbg_init_state;
2919+static mbedtls_ctr_drbg_context ctr_drbg;
2920+static mbedtls_entropy_context entropy;
2921+
2922+#ifdef CRYPTO_MBEDTLS_CRYPTO_BIGNUM
2923+#include <mbedtls/bignum.h>
2924+static mbedtls_mpi mpi_sw_A;
2925+#endif
2926+
2927+__attribute_cold__
2928+__attribute_noinline__
2929+static mbedtls_ctr_drbg_context * ctr_drbg_init(void)
2930+{
2931+ mbedtls_ctr_drbg_init(&ctr_drbg);
2932+ mbedtls_entropy_init(&entropy);
2933+ if (mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
2934+ NULL, 0)) {
2935+ wpa_printf(MSG_ERROR, "Init of random number generator failed");
2936+ /* XXX: abort? */
2937+ }
2938+ else
2939+ ctr_drbg_init_state = 1;
2940+
2941+ return &ctr_drbg;
2942+}
2943+
2944+__attribute_cold__
2945+void crypto_unload(void)
2946+{
2947+ if (ctr_drbg_init_state) {
2948+ mbedtls_ctr_drbg_free(&ctr_drbg);
2949+ mbedtls_entropy_free(&entropy);
2950+ #ifdef CRYPTO_MBEDTLS_CRYPTO_BIGNUM
2951+ mbedtls_mpi_free(&mpi_sw_A);
2952+ #endif
2953+ ctr_drbg_init_state = 0;
2954+ }
2955+}
2956+
2957+/* init ctr_drbg on first use
2958+ * crypto_global_init() and crypto_global_deinit() are not available here
2959+ * (available only when CONFIG_TLS=internal, which is not CONFIG_TLS=mbedtls) */
2960+mbedtls_ctr_drbg_context * crypto_mbedtls_ctr_drbg(void); /*(not in header)*/
2961+inline
2962+mbedtls_ctr_drbg_context * crypto_mbedtls_ctr_drbg(void)
2963+{
2964+ return ctr_drbg_init_state ? &ctr_drbg : ctr_drbg_init();
2965+}
2966+
2967+#ifdef CRYPTO_MBEDTLS_CONFIG_FIPS
2968+int crypto_get_random(void *buf, size_t len)
2969+{
2970+ return mbedtls_ctr_drbg_random(crypto_mbedtls_ctr_drbg(),buf,len) ? -1 : 0;
2971+}
2972+#endif
2973+
2974+
2975+#if 1
2976+
2977+/* tradeoff: slightly smaller code size here at cost of slight increase
2978+ * in instructions and function calls at runtime versus the expanded
2979+ * per-message-digest code that follows in #else (~0.5 kib .text larger) */
2980+
2981+__attribute_noinline__
2982+static int md_vector(size_t num_elem, const u8 *addr[], const size_t *len,
2983+ u8 *mac, mbedtls_md_type_t md_type)
2984+{
2985+ if (TEST_FAIL())
2986+ return -1;
2987+
2988+ mbedtls_md_context_t ctx;
2989+ mbedtls_md_init(&ctx);
2990+ if (mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 0) != 0){
2991+ mbedtls_md_free(&ctx);
2992+ return -1;
2993+ }
2994+ mbedtls_md_starts(&ctx);
2995+ for (size_t i = 0; i < num_elem; ++i)
2996+ mbedtls_md_update(&ctx, addr[i], len[i]);
2997+ mbedtls_md_finish(&ctx, mac);
2998+ mbedtls_md_free(&ctx);
2999+ return 0;
3000+}
3001+
3002+#ifdef MBEDTLS_SHA512_C
3003+int sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
3004+{
3005+ return md_vector(num_elem, addr, len, mac, MBEDTLS_MD_SHA512);
3006+}
3007+
3008+int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
3009+{
3010+ return md_vector(num_elem, addr, len, mac, MBEDTLS_MD_SHA384);
3011+}
3012+#endif
3013+
3014+#ifdef MBEDTLS_SHA256_C
3015+int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
3016+{
3017+ return md_vector(num_elem, addr, len, mac, MBEDTLS_MD_SHA256);
3018+}
3019+#endif
3020+
3021+#ifdef MBEDTLS_SHA1_C
3022+int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
3023+{
3024+ return md_vector(num_elem, addr, len, mac, MBEDTLS_MD_SHA1);
3025+}
3026+#endif
3027+
3028+#ifdef MBEDTLS_MD5_C
3029+int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
3030+{
3031+ return md_vector(num_elem, addr, len, mac, MBEDTLS_MD_MD5);
3032+}
3033+#endif
3034+
3035+#ifdef MBEDTLS_MD4_C
3036+#include <mbedtls/md4.h>
3037+int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
3038+{
3039+ return md_vector(num_elem, addr, len, mac, MBEDTLS_MD_MD4);
3040+}
3041+#endif
3042+
3043+#else /* expanded per-message-digest functions */
3044+
3045+#ifdef MBEDTLS_SHA512_C
3046+#include <mbedtls/sha512.h>
3047+__attribute_noinline__
3048+static int sha384_512_vector(size_t num_elem, const u8 *addr[],
3049+ const size_t *len, u8 *mac, int is384)
3050+{
3051+ if (TEST_FAIL())
3052+ return -1;
3053+
3054+ struct mbedtls_sha512_context ctx;
3055+ mbedtls_sha512_init(&ctx);
3056+ #if MBEDTLS_VERSION_MAJOR >= 3
3057+ mbedtls_sha512_starts(&ctx, is384);
3058+ for (size_t i = 0; i < num_elem; ++i)
3059+ mbedtls_sha512_update(&ctx, addr[i], len[i]);
3060+ mbedtls_sha512_finish(&ctx, mac);
3061+ #else
3062+ mbedtls_sha512_starts_ret(&ctx, is384);
3063+ for (size_t i = 0; i < num_elem; ++i)
3064+ mbedtls_sha512_update_ret(&ctx, addr[i], len[i]);
3065+ mbedtls_sha512_finish_ret(&ctx, mac);
3066+ #endif
3067+ mbedtls_sha512_free(&ctx);
3068+ return 0;
3069+}
3070+
3071+int sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
3072+{
3073+ return sha384_512_vector(num_elem, addr, len, mac, 0);
3074+}
3075+
3076+int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
3077+{
3078+ return sha384_512_vector(num_elem, addr, len, mac, 1);
3079+}
3080+#endif
3081+
3082+#ifdef MBEDTLS_SHA256_C
3083+#include <mbedtls/sha256.h>
3084+int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
3085+{
3086+ if (TEST_FAIL())
3087+ return -1;
3088+
3089+ struct mbedtls_sha256_context ctx;
3090+ mbedtls_sha256_init(&ctx);
3091+ #if MBEDTLS_VERSION_MAJOR >= 3
3092+ mbedtls_sha256_starts(&ctx, 0);
3093+ for (size_t i = 0; i < num_elem; ++i)
3094+ mbedtls_sha256_update(&ctx, addr[i], len[i]);
3095+ mbedtls_sha256_finish(&ctx, mac);
3096+ #else
3097+ mbedtls_sha256_starts_ret(&ctx, 0);
3098+ for (size_t i = 0; i < num_elem; ++i)
3099+ mbedtls_sha256_update_ret(&ctx, addr[i], len[i]);
3100+ mbedtls_sha256_finish_ret(&ctx, mac);
3101+ #endif
3102+ mbedtls_sha256_free(&ctx);
3103+ return 0;
3104+}
3105+#endif
3106+
3107+#ifdef MBEDTLS_SHA1_C
3108+#include <mbedtls/sha1.h>
3109+int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
3110+{
3111+ if (TEST_FAIL())
3112+ return -1;
3113+
3114+ struct mbedtls_sha1_context ctx;
3115+ mbedtls_sha1_init(&ctx);
3116+ #if MBEDTLS_VERSION_MAJOR >= 3
3117+ mbedtls_sha1_starts(&ctx);
3118+ for (size_t i = 0; i < num_elem; ++i)
3119+ mbedtls_sha1_update(&ctx, addr[i], len[i]);
3120+ mbedtls_sha1_finish(&ctx, mac);
3121+ #else
3122+ mbedtls_sha1_starts_ret(&ctx);
3123+ for (size_t i = 0; i < num_elem; ++i)
3124+ mbedtls_sha1_update_ret(&ctx, addr[i], len[i]);
3125+ mbedtls_sha1_finish_ret(&ctx, mac);
3126+ #endif
3127+ mbedtls_sha1_free(&ctx);
3128+ return 0;
3129+}
3130+#endif
3131+
3132+#ifdef MBEDTLS_MD5_C
3133+#include <mbedtls/md5.h>
3134+int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
3135+{
3136+ if (TEST_FAIL())
3137+ return -1;
3138+
3139+ struct mbedtls_md5_context ctx;
3140+ mbedtls_md5_init(&ctx);
3141+ #if MBEDTLS_VERSION_MAJOR >= 3
3142+ mbedtls_md5_starts(&ctx);
3143+ for (size_t i = 0; i < num_elem; ++i)
3144+ mbedtls_md5_update(&ctx, addr[i], len[i]);
3145+ mbedtls_md5_finish(&ctx, mac);
3146+ #else
3147+ mbedtls_md5_starts_ret(&ctx);
3148+ for (size_t i = 0; i < num_elem; ++i)
3149+ mbedtls_md5_update_ret(&ctx, addr[i], len[i]);
3150+ mbedtls_md5_finish_ret(&ctx, mac);
3151+ #endif
3152+ mbedtls_md5_free(&ctx);
3153+ return 0;
3154+}
3155+#endif
3156+
3157+#ifdef MBEDTLS_MD4_C
3158+#include <mbedtls/md4.h>
3159+int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
3160+{
3161+ if (TEST_FAIL())
3162+ return -1;
3163+
3164+ struct mbedtls_md4_context ctx;
3165+ mbedtls_md4_init(&ctx);
3166+ mbedtls_md4_starts_ret(&ctx);
3167+ for (size_t i = 0; i < num_elem; ++i)
3168+ mbedtls_md4_update_ret(&ctx, addr[i], len[i]);
3169+ mbedtls_md4_finish_ret(&ctx, mac);
3170+ mbedtls_md4_free(&ctx);
3171+ return 0;
3172+}
3173+#endif
3174+
3175+#endif /* expanded per-message-digest functions */
3176+
3177+
3178+__attribute_noinline__
3179+static int hmac_vector(const u8 *key, size_t key_len, size_t num_elem,
3180+ const u8 *addr[], const size_t *len, u8 *mac,
3181+ mbedtls_md_type_t md_type)
3182+{
3183+ if (TEST_FAIL())
3184+ return -1;
3185+
3186+ mbedtls_md_context_t ctx;
3187+ mbedtls_md_init(&ctx);
3188+ if (mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 1) != 0){
3189+ mbedtls_md_free(&ctx);
3190+ return -1;
3191+ }
3192+ mbedtls_md_hmac_starts(&ctx, key, key_len);
3193+ for (size_t i = 0; i < num_elem; ++i)
3194+ mbedtls_md_hmac_update(&ctx, addr[i], len[i]);
3195+ mbedtls_md_hmac_finish(&ctx, mac);
3196+ mbedtls_md_free(&ctx);
3197+ return 0;
3198+}
3199+
3200+#ifdef MBEDTLS_SHA512_C
3201+int hmac_sha512_vector(const u8 *key, size_t key_len, size_t num_elem,
3202+ const u8 *addr[], const size_t *len, u8 *mac)
3203+{
3204+ return hmac_vector(key, key_len, num_elem, addr, len, mac,
3205+ MBEDTLS_MD_SHA512);
3206+}
3207+
3208+int hmac_sha512(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
3209+ u8 *mac)
3210+{
3211+ return hmac_vector(key, key_len, 1, &data, &data_len, mac,
3212+ MBEDTLS_MD_SHA512);
3213+}
3214+
3215+int hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem,
3216+ const u8 *addr[], const size_t *len, u8 *mac)
3217+{
3218+ return hmac_vector(key, key_len, num_elem, addr, len, mac,
3219+ MBEDTLS_MD_SHA384);
3220+}
3221+
3222+int hmac_sha384(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
3223+ u8 *mac)
3224+{
3225+ return hmac_vector(key, key_len, 1, &data, &data_len, mac,
3226+ MBEDTLS_MD_SHA384);
3227+}
3228+#endif
3229+
3230+#ifdef MBEDTLS_SHA256_C
3231+int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
3232+ const u8 *addr[], const size_t *len, u8 *mac)
3233+{
3234+ return hmac_vector(key, key_len, num_elem, addr, len, mac,
3235+ MBEDTLS_MD_SHA256);
3236+}
3237+
3238+int hmac_sha256(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
3239+ u8 *mac)
3240+{
3241+ return hmac_vector(key, key_len, 1, &data, &data_len, mac,
3242+ MBEDTLS_MD_SHA256);
3243+}
3244+#endif
3245+
3246+#ifdef MBEDTLS_SHA1_C
3247+int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
3248+ const u8 *addr[], const size_t *len, u8 *mac)
3249+{
3250+ return hmac_vector(key, key_len, num_elem, addr, len, mac,
3251+ MBEDTLS_MD_SHA1);
3252+}
3253+
3254+int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
3255+ u8 *mac)
3256+{
3257+ return hmac_vector(key, key_len, 1, &data, &data_len, mac,
3258+ MBEDTLS_MD_SHA1);
3259+}
3260+#endif
3261+
3262+#ifdef MBEDTLS_MD5_C
3263+int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
3264+ const u8 *addr[], const size_t *len, u8 *mac)
3265+{
3266+ return hmac_vector(key, key_len, num_elem, addr, len, mac,
3267+ MBEDTLS_MD_MD5);
3268+}
3269+
3270+int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
3271+ u8 *mac)
3272+{
3273+ return hmac_vector(key, key_len, 1, &data, &data_len, mac,
3274+ MBEDTLS_MD_MD5);
3275+}
3276+#endif
3277+
3278+
3279+#if defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA512_C)
3280+
3281+#if defined(CRYPTO_MBEDTLS_HMAC_KDF_SHA256) \
3282+ || defined(CRYPTO_MBEDTLS_HMAC_KDF_SHA384) \
3283+ || defined(CRYPTO_MBEDTLS_HMAC_KDF_SHA512)
3284+
3285+#include <mbedtls/hkdf.h>
3286+
3287+/* sha256-kdf.c sha384-kdf.c sha512-kdf.c */
3288+
3289+/* HMAC-SHA256 KDF (RFC 5295) and HKDF-Expand(SHA256) (RFC 5869) */
3290+/* HMAC-SHA384 KDF (RFC 5295) and HKDF-Expand(SHA384) (RFC 5869) */
3291+/* HMAC-SHA512 KDF (RFC 5295) and HKDF-Expand(SHA512) (RFC 5869) */
3292+__attribute_noinline__
3293+static int hmac_kdf_expand(const u8 *prk, size_t prk_len,
3294+ const char *label, const u8 *info, size_t info_len,
3295+ u8 *okm, size_t okm_len, mbedtls_md_type_t md_type)
3296+{
3297+ if (TEST_FAIL())
3298+ return -1;
3299+
3300+ const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_type);
3301+ #ifdef MBEDTLS_HKDF_C
3302+ if (label == NULL) /* RFC 5869 HKDF-Expand when (label == NULL) */
3303+ return mbedtls_hkdf_expand(md_info, prk, prk_len, info,
3304+ info_len, okm, okm_len) ? -1 : 0;
3305+ #endif
3306+
3307+ const size_t mac_len = mbedtls_md_get_size(md_info);
3308+ /* okm_len must not exceed 255 times hash len (RFC 5869 Section 2.3) */
3309+ if (okm_len > ((mac_len << 8) - mac_len))
3310+ return -1;
3311+
3312+ mbedtls_md_context_t ctx;
3313+ mbedtls_md_init(&ctx);
3314+ if (mbedtls_md_setup(&ctx, md_info, 1) != 0) {
3315+ mbedtls_md_free(&ctx);
3316+ return -1;
3317+ }
3318+ mbedtls_md_hmac_starts(&ctx, prk, prk_len);
3319+
3320+ u8 iter = 1;
3321+ const u8 *addr[4] = { okm, (const u8 *)label, info, &iter };
3322+ size_t len[4] = { 0, label ? os_strlen(label)+1 : 0, info_len, 1 };
3323+
3324+ for (; okm_len >= mac_len; okm_len -= mac_len, ++iter) {
3325+ for (size_t i = 0; i < ARRAY_SIZE(addr); ++i)
3326+ mbedtls_md_hmac_update(&ctx, addr[i], len[i]);
3327+ mbedtls_md_hmac_finish(&ctx, okm);
3328+ mbedtls_md_hmac_reset(&ctx);
3329+ addr[0] = okm;
3330+ okm += mac_len;
3331+ len[0] = mac_len; /*(include digest in subsequent rounds)*/
3332+ }
3333+
3334+ if (okm_len) {
3335+ u8 hash[MBEDTLS_MD_MAX_SIZE];
3336+ for (size_t i = 0; i < ARRAY_SIZE(addr); ++i)
3337+ mbedtls_md_hmac_update(&ctx, addr[i], len[i]);
3338+ mbedtls_md_hmac_finish(&ctx, hash);
3339+ os_memcpy(okm, hash, okm_len);
3340+ forced_memzero(hash, mac_len);
3341+ }
3342+
3343+ mbedtls_md_free(&ctx);
3344+ return 0;
3345+}
3346+
3347+#ifdef MBEDTLS_SHA512_C
3348+#ifdef CRYPTO_MBEDTLS_HMAC_KDF_SHA512
3349+int hmac_sha512_kdf(const u8 *secret, size_t secret_len,
3350+ const char *label, const u8 *seed, size_t seed_len,
3351+ u8 *out, size_t outlen)
3352+{
3353+ return hmac_kdf_expand(secret, secret_len, label, seed, seed_len,
3354+ out, outlen, MBEDTLS_MD_SHA512);
3355+}
3356+#endif
3357+
3358+#ifdef CRYPTO_MBEDTLS_HMAC_KDF_SHA384
3359+int hmac_sha384_kdf(const u8 *secret, size_t secret_len,
3360+ const char *label, const u8 *seed, size_t seed_len,
3361+ u8 *out, size_t outlen)
3362+{
3363+ return hmac_kdf_expand(secret, secret_len, label, seed, seed_len,
3364+ out, outlen, MBEDTLS_MD_SHA384);
3365+}
3366+#endif
3367+#endif
3368+
3369+#ifdef MBEDTLS_SHA256_C
3370+#ifdef CRYPTO_MBEDTLS_HMAC_KDF_SHA256
3371+int hmac_sha256_kdf(const u8 *secret, size_t secret_len,
3372+ const char *label, const u8 *seed, size_t seed_len,
3373+ u8 *out, size_t outlen)
3374+{
3375+ return hmac_kdf_expand(secret, secret_len, label, seed, seed_len,
3376+ out, outlen, MBEDTLS_MD_SHA256);
3377+}
3378+#endif
3379+#endif
3380+
3381+#endif /* CRYPTO_MBEDTLS_HMAC_KDF_* */
3382+
3383+
3384+/* sha256-prf.c sha384-prf.c sha512-prf.c */
3385+
3386+/* hmac_prf_bits - IEEE Std 802.11ac-2013, 11.6.1.7.2 Key derivation function */
3387+__attribute_noinline__
3388+static int hmac_prf_bits(const u8 *key, size_t key_len, const char *label,
3389+ const u8 *data, size_t data_len, u8 *buf,
3390+ size_t buf_len_bits, mbedtls_md_type_t md_type)
3391+{
3392+ if (TEST_FAIL())
3393+ return -1;
3394+
3395+ mbedtls_md_context_t ctx;
3396+ mbedtls_md_init(&ctx);
3397+ const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_type);
3398+ if (mbedtls_md_setup(&ctx, md_info, 1) != 0) {
3399+ mbedtls_md_free(&ctx);
3400+ return -1;
3401+ }
3402+ mbedtls_md_hmac_starts(&ctx, key, key_len);
3403+
3404+ u16 ctr, n_le = host_to_le16(buf_len_bits);
3405+ const u8 * const addr[] = { (u8 *)&ctr,(u8 *)label,data,(u8 *)&n_le };
3406+ const size_t len[] = { 2, os_strlen(label), data_len, 2 };
3407+ const size_t mac_len = mbedtls_md_get_size(md_info);
3408+ size_t buf_len = (buf_len_bits + 7) / 8;
3409+ for (ctr = 1; buf_len >= mac_len; buf_len -= mac_len, ++ctr) {
3410+ #if __BYTE_ORDER == __BIG_ENDIAN
3411+ ctr = host_to_le16(ctr);
3412+ #endif
3413+ for (size_t i = 0; i < ARRAY_SIZE(addr); ++i)
3414+ mbedtls_md_hmac_update(&ctx, addr[i], len[i]);
3415+ mbedtls_md_hmac_finish(&ctx, buf);
3416+ mbedtls_md_hmac_reset(&ctx);
3417+ buf += mac_len;
3418+ #if __BYTE_ORDER == __BIG_ENDIAN
3419+ ctr = le_to_host16(ctr);
3420+ #endif
3421+ }
3422+
3423+ if (buf_len) {
3424+ u8 hash[MBEDTLS_MD_MAX_SIZE];
3425+ #if __BYTE_ORDER == __BIG_ENDIAN
3426+ ctr = host_to_le16(ctr);
3427+ #endif
3428+ for (size_t i = 0; i < ARRAY_SIZE(addr); ++i)
3429+ mbedtls_md_hmac_update(&ctx, addr[i], len[i]);
3430+ mbedtls_md_hmac_finish(&ctx, hash);
3431+ os_memcpy(buf, hash, buf_len);
3432+ buf += buf_len;
3433+ forced_memzero(hash, mac_len);
3434+ }
3435+
3436+ /* Mask out unused bits in last octet if it does not use all the bits */
3437+ if ((buf_len_bits &= 0x7))
3438+ buf[-1] &= (u8)(0xff << (8 - buf_len_bits));
3439+
3440+ mbedtls_md_free(&ctx);
3441+ return 0;
3442+}
3443+
3444+#ifdef MBEDTLS_SHA512_C
3445+int sha512_prf(const u8 *key, size_t key_len, const char *label,
3446+ const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
3447+{
3448+ return hmac_prf_bits(key, key_len, label, data, data_len, buf,
3449+ buf_len * 8, MBEDTLS_MD_SHA512);
3450+}
3451+
3452+int sha384_prf(const u8 *key, size_t key_len, const char *label,
3453+ const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
3454+{
3455+ return hmac_prf_bits(key, key_len, label, data, data_len, buf,
3456+ buf_len * 8, MBEDTLS_MD_SHA384);
3457+}
3458+#endif
3459+
3460+#ifdef MBEDTLS_SHA256_C
3461+int sha256_prf(const u8 *key, size_t key_len, const char *label,
3462+ const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
3463+{
3464+ return hmac_prf_bits(key, key_len, label, data, data_len, buf,
3465+ buf_len * 8, MBEDTLS_MD_SHA256);
3466+}
3467+
3468+int sha256_prf_bits(const u8 *key, size_t key_len, const char *label,
3469+ const u8 *data, size_t data_len, u8 *buf,
3470+ size_t buf_len_bits)
3471+{
3472+ return hmac_prf_bits(key, key_len, label, data, data_len, buf,
3473+ buf_len_bits, MBEDTLS_MD_SHA256);
3474+}
3475+#endif
3476+
3477+#endif /* MBEDTLS_SHA256_C || MBEDTLS_SHA512_C */
3478+
3479+
3480+#ifdef MBEDTLS_SHA1_C
3481+
3482+/* sha1-prf.c */
3483+
3484+/* sha1_prf - SHA1-based Pseudo-Random Function (PRF) (IEEE 802.11i, 8.5.1.1) */
3485+
3486+int sha1_prf(const u8 *key, size_t key_len, const char *label,
3487+ const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
3488+{
3489+ /*(note: algorithm differs from hmac_prf_bits() */
3490+ /*(note: smaller code size instead of expanding hmac_sha1_vector()
3491+ * as is done in hmac_prf_bits(); not expecting large num of loops) */
3492+ u8 counter = 0;
3493+ const u8 *addr[] = { (u8 *)label, data, &counter };
3494+ const size_t len[] = { os_strlen(label)+1, data_len, 1 };
3495+
3496+ for (; buf_len >= SHA1_MAC_LEN; buf_len -= SHA1_MAC_LEN, ++counter) {
3497+ if (hmac_sha1_vector(key, key_len, 3, addr, len, buf))
3498+ return -1;
3499+ buf += SHA1_MAC_LEN;
3500+ }
3501+
3502+ if (buf_len) {
3503+ u8 hash[SHA1_MAC_LEN];
3504+ if (hmac_sha1_vector(key, key_len, 3, addr, len, hash))
3505+ return -1;
3506+ os_memcpy(buf, hash, buf_len);
3507+ forced_memzero(hash, sizeof(hash));
3508+ }
3509+
3510+ return 0;
3511+}
3512+
3513+#ifdef CRYPTO_MBEDTLS_SHA1_T_PRF
3514+
3515+/* sha1-tprf.c */
3516+
3517+/* sha1_t_prf - EAP-FAST Pseudo-Random Function (T-PRF) (RFC 4851,Section 5.5)*/
3518+
3519+int sha1_t_prf(const u8 *key, size_t key_len, const char *label,
3520+ const u8 *seed, size_t seed_len, u8 *buf, size_t buf_len)
3521+{
3522+ /*(note: algorithm differs from hmac_prf_bits() and hmac_kdf() above)*/
3523+ /*(note: smaller code size instead of expanding hmac_sha1_vector()
3524+ * as is done in hmac_prf_bits(); not expecting large num of loops) */
3525+ u8 ctr;
3526+ u16 olen = host_to_be16(buf_len);
3527+ const u8 *addr[] = { buf, (u8 *)label, seed, (u8 *)&olen, &ctr };
3528+ size_t len[] = { 0, os_strlen(label)+1, seed_len, 2, 1 };
3529+
3530+ for (ctr = 1; buf_len >= SHA1_MAC_LEN; buf_len -= SHA1_MAC_LEN, ++ctr) {
3531+ if (hmac_sha1_vector(key, key_len, 5, addr, len, buf))
3532+ return -1;
3533+ addr[0] = buf;
3534+ buf += SHA1_MAC_LEN;
3535+ len[0] = SHA1_MAC_LEN; /*(include digest in subsequent rounds)*/
3536+ }
3537+
3538+ if (buf_len) {
3539+ u8 hash[SHA1_MAC_LEN];
3540+ if (hmac_sha1_vector(key, key_len, 5, addr, len, hash))
3541+ return -1;
3542+ os_memcpy(buf, hash, buf_len);
3543+ forced_memzero(hash, sizeof(hash));
3544+ }
3545+
3546+ return 0;
3547+}
3548+
3549+#endif /* CRYPTO_MBEDTLS_SHA1_T_PRF */
3550+
3551+#ifdef CRYPTO_MBEDTLS_FIPS186_2_PRF
3552+
3553+/* fips_prf_internal.c sha1-internal.c */
3554+
3555+/* used only by src/eap_common/eap_sim_common.c:eap_sim_prf()
3556+ * for eap_sim_derive_keys() and eap_sim_derive_keys_reauth()
3557+ * where xlen is 160 */
3558+
3559+int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
3560+{
3561+ /* FIPS 186-2 + change notice 1 */
3562+
3563+ mbedtls_sha1_context ctx;
3564+ u8 * const xkey = ctx.MBEDTLS_PRIVATE(buffer);
3565+ u32 * const xstate = ctx.MBEDTLS_PRIVATE(state);
3566+ const u32 xstate_init[] =
3567+ { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 };
3568+
3569+ mbedtls_sha1_init(&ctx);
3570+ os_memcpy(xkey, seed, seed_len < 64 ? seed_len : 64);
3571+
3572+ /* note: does not fill extra bytes if (xlen % 20) (SHA1_MAC_LEN) */
3573+ for (; xlen >= 20; xlen -= 20) {
3574+ /* XSEED_j = 0 */
3575+ /* XVAL = (XKEY + XSEED_j) mod 2^b */
3576+
3577+ /* w_i = G(t, XVAL) */
3578+ os_memcpy(xstate, xstate_init, sizeof(xstate_init));
3579+ mbedtls_internal_sha1_process(&ctx, xkey);
3580+
3581+ #if __BYTE_ORDER == __LITTLE_ENDIAN
3582+ xstate[0] = host_to_be32(xstate[0]);
3583+ xstate[1] = host_to_be32(xstate[1]);
3584+ xstate[2] = host_to_be32(xstate[2]);
3585+ xstate[3] = host_to_be32(xstate[3]);
3586+ xstate[4] = host_to_be32(xstate[4]);
3587+ #endif
3588+ os_memcpy(x, xstate, 20);
3589+ if (xlen == 20) /*(done; skip prep for next loop)*/
3590+ break;
3591+
3592+ /* XKEY = (1 + XKEY + w_i) mod 2^b */
3593+ for (u32 carry = 1, k = 20; k-- > 0; carry >>= 8)
3594+ xkey[k] = (carry += xkey[k] + x[k]) & 0xff;
3595+ x += 20;
3596+ /* x_j = w_0|w_1 (each pair of iterations through loop)*/
3597+ }
3598+
3599+ mbedtls_sha1_free(&ctx);
3600+ return 0;
3601+}
3602+
3603+#endif /* CRYPTO_MBEDTLS_FIPS186_2_PRF */
3604+
3605+#endif /* MBEDTLS_SHA1_C */
3606+
3607+
3608+#ifdef CRYPTO_MBEDTLS_DES_ENCRYPT
3609+#ifdef MBEDTLS_DES_C
3610+#include <mbedtls/des.h>
3611+int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
3612+{
3613+ u8 pkey[8], next, tmp;
3614+ int i;
3615+
3616+ /* Add parity bits to the key */
3617+ next = 0;
3618+ for (i = 0; i < 7; i++) {
3619+ tmp = key[i];
3620+ pkey[i] = (tmp >> i) | next | 1;
3621+ next = tmp << (7 - i);
3622+ }
3623+ pkey[i] = next | 1;
3624+
3625+ mbedtls_des_context des;
3626+ mbedtls_des_init(&des);
3627+ int ret = mbedtls_des_setkey_enc(&des, pkey)
3628+ || mbedtls_des_crypt_ecb(&des, clear, cypher) ? -1 : 0;
3629+ mbedtls_des_free(&des);
3630+ return ret;
3631+}
3632+#else
3633+#include "des-internal.c"/* pull in hostap local implementation */
3634+#endif
3635+#endif
3636+
3637+
3638+#ifdef CRYPTO_MBEDTLS_PBKDF2_SHA1
3639+/* sha1-pbkdf2.c */
3640+#include <mbedtls/pkcs5.h>
3641+int pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len,
3642+ int iterations, u8 *buf, size_t buflen)
3643+{
3644+ #if MBEDTLS_VERSION_NUMBER >= 0x03020200 /* mbedtls 3.2.2 */
3645+ return mbedtls_pkcs5_pbkdf2_hmac_ext(MBEDTLS_MD_SHA1,
3646+ (const u8 *)passphrase, os_strlen(passphrase),
3647+ ssid, ssid_len, iterations, 32, buf) ? -1 : 0;
3648+ #else
3649+ const mbedtls_md_info_t *md_info;
3650+ md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
3651+ if (md_info == NULL)
3652+ return -1;
3653+ mbedtls_md_context_t ctx;
3654+ mbedtls_md_init(&ctx);
3655+ int ret = mbedtls_md_setup(&ctx, md_info, 1)
3656+ || mbedtls_pkcs5_pbkdf2_hmac(&ctx,
3657+ (const u8 *)passphrase, os_strlen(passphrase),
3658+ ssid, ssid_len, iterations, 32, buf) ? -1 : 0;
3659+ mbedtls_md_free(&ctx);
3660+ return ret;
3661+ #endif
3662+}
3663+#endif
3664+
3665+
3666+/*#include "aes.h"*/ /* prototypes also included in "crypto.h" */
3667+
3668+static void *aes_crypt_init_mode(const u8 *key, size_t len, int mode)
3669+{
3670+ if (TEST_FAIL())
3671+ return NULL;
3672+
3673+ mbedtls_aes_context *aes = os_malloc(sizeof(*aes));
3674+ if (!aes)
3675+ return NULL;
3676+
3677+ mbedtls_aes_init(aes);
3678+ if ((mode == MBEDTLS_AES_ENCRYPT
3679+ ? mbedtls_aes_setkey_enc(aes, key, len * 8)
3680+ : mbedtls_aes_setkey_dec(aes, key, len * 8)) == 0)
3681+ return aes;
3682+
3683+ mbedtls_aes_free(aes);
3684+ os_free(aes);
3685+ return NULL;
3686+}
3687+
3688+void *aes_encrypt_init(const u8 *key, size_t len)
3689+{
3690+ return aes_crypt_init_mode(key, len, MBEDTLS_AES_ENCRYPT);
3691+}
3692+
3693+int aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
3694+{
3695+ return mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, plain, crypt);
3696+}
3697+
3698+void aes_encrypt_deinit(void *ctx)
3699+{
3700+ mbedtls_aes_free(ctx);
3701+ os_free(ctx);
3702+}
3703+
3704+void *aes_decrypt_init(const u8 *key, size_t len)
3705+{
3706+ return aes_crypt_init_mode(key, len, MBEDTLS_AES_DECRYPT);
3707+}
3708+
3709+int aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
3710+{
3711+ return mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_DECRYPT, crypt, plain);
3712+}
3713+
3714+void aes_decrypt_deinit(void *ctx)
3715+{
3716+ mbedtls_aes_free(ctx);
3717+ os_free(ctx);
3718+}
3719+
3720+
3721+#include "aes_wrap.h"
3722+
3723+
3724+#ifdef MBEDTLS_NIST_KW_C
3725+
3726+#include <mbedtls/nist_kw.h>
3727+
3728+/* aes-wrap.c */
3729+int aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain, u8 *cipher)
3730+{
3731+ if (TEST_FAIL())
3732+ return -1;
3733+
3734+ mbedtls_nist_kw_context ctx;
3735+ mbedtls_nist_kw_init(&ctx);
3736+ size_t olen;
3737+ int ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
3738+ kek, kek_len*8, 1)
3739+ || mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KW, plain, n*8,
3740+ cipher, &olen, (n+1)*8) ? -1 : 0;
3741+ mbedtls_nist_kw_free(&ctx);
3742+ return ret;
3743+}
3744+
3745+/* aes-unwrap.c */
3746+int aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher, u8 *plain)
3747+{
3748+ if (TEST_FAIL())
3749+ return -1;
3750+
3751+ mbedtls_nist_kw_context ctx;
3752+ mbedtls_nist_kw_init(&ctx);
3753+ size_t olen;
3754+ int ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
3755+ kek, kek_len*8, 0)
3756+ || mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KW, cipher,
3757+ (n+1)*8, plain, &olen, n*8) ? -1 : 0;
3758+ mbedtls_nist_kw_free(&ctx);
3759+ return ret;
3760+}
3761+
3762+#else
3763+
3764+#ifndef CRYPTO_MBEDTLS_CONFIG_FIPS
3765+#include "aes-wrap.c" /* pull in hostap local implementation */
3766+#include "aes-unwrap.c" /* pull in hostap local implementation */
3767+#endif
3768+
3769+#endif /* MBEDTLS_NIST_KW_C */
3770+
3771+
3772+#ifdef MBEDTLS_CMAC_C
3773+
3774+/* aes-omac1.c */
3775+
3776+#include <mbedtls/cmac.h>
3777+
3778+int omac1_aes_vector(
3779+ const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[],
3780+ const size_t *len, u8 *mac)
3781+{
3782+ if (TEST_FAIL())
3783+ return -1;
3784+
3785+ mbedtls_cipher_type_t cipher_type;
3786+ switch (key_len) {
3787+ case 16: cipher_type = MBEDTLS_CIPHER_AES_128_ECB; break;
3788+ case 24: cipher_type = MBEDTLS_CIPHER_AES_192_ECB; break;
3789+ case 32: cipher_type = MBEDTLS_CIPHER_AES_256_ECB; break;
3790+ default: return -1;
3791+ }
3792+ const mbedtls_cipher_info_t *cipher_info;
3793+ cipher_info = mbedtls_cipher_info_from_type(cipher_type);
3794+ if (cipher_info == NULL)
3795+ return -1;
3796+
3797+ mbedtls_cipher_context_t ctx;
3798+ mbedtls_cipher_init(&ctx);
3799+ int ret = -1;
3800+ if (mbedtls_cipher_setup(&ctx, cipher_info) == 0
3801+ && mbedtls_cipher_cmac_starts(&ctx, key, key_len*8) == 0) {
3802+ ret = 0;
3803+ for (size_t i = 0; i < num_elem && ret == 0; ++i)
3804+ ret = mbedtls_cipher_cmac_update(&ctx, addr[i], len[i]);
3805+ }
3806+ if (ret == 0)
3807+ ret = mbedtls_cipher_cmac_finish(&ctx, mac);
3808+ mbedtls_cipher_free(&ctx);
3809+ return ret ? -1 : 0;
3810+}
3811+
3812+int omac1_aes_128_vector(const u8 *key, size_t num_elem,
3813+ const u8 *addr[], const size_t *len,
3814+ u8 *mac)
3815+{
3816+ return omac1_aes_vector(key, 16, num_elem, addr, len, mac);
3817+}
3818+
3819+int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
3820+{
3821+ return omac1_aes_vector(key, 16, 1, &data, &data_len, mac);
3822+}
3823+
3824+int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
3825+{
3826+ return omac1_aes_vector(key, 32, 1, &data, &data_len, mac);
3827+}
3828+
3829+#else
3830+
3831+#include "aes-omac1.c" /* pull in hostap local implementation */
3832+
3833+#ifndef MBEDTLS_AES_BLOCK_SIZE
3834+#define MBEDTLS_AES_BLOCK_SIZE 16
3835+#endif
3836+
3837+#endif /* MBEDTLS_CMAC_C */
3838+
3839+
3840+/* These interfaces can be inefficient when used in loops, as the overhead of
3841+ * initialization each call is large for each block input (e.g. 16 bytes) */
3842+
3843+
3844+/* aes-encblock.c */
3845+int aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out)
3846+{
3847+ if (TEST_FAIL())
3848+ return -1;
3849+
3850+ mbedtls_aes_context aes;
3851+ mbedtls_aes_init(&aes);
3852+ int ret = mbedtls_aes_setkey_enc(&aes, key, 128)
3853+ || mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_ENCRYPT, in, out)
3854+ ? -1
3855+ : 0;
3856+ mbedtls_aes_free(&aes);
3857+ return ret;
3858+}
3859+
3860+
3861+/* aes-ctr.c */
3862+int aes_ctr_encrypt(const u8 *key, size_t key_len, const u8 *nonce,
3863+ u8 *data, size_t data_len)
3864+{
3865+ if (TEST_FAIL())
3866+ return -1;
3867+
3868+ unsigned char counter[MBEDTLS_AES_BLOCK_SIZE];
3869+ unsigned char stream_block[MBEDTLS_AES_BLOCK_SIZE];
3870+ os_memcpy(counter, nonce, MBEDTLS_AES_BLOCK_SIZE);/*(must be writable)*/
3871+
3872+ mbedtls_aes_context ctx;
3873+ mbedtls_aes_init(&ctx);
3874+ size_t nc_off = 0;
3875+ int ret = mbedtls_aes_setkey_enc(&ctx, key, key_len*8)
3876+ || mbedtls_aes_crypt_ctr(&ctx, data_len, &nc_off,
3877+ counter, stream_block,
3878+ data, data) ? -1 : 0;
3879+ forced_memzero(stream_block, sizeof(stream_block));
3880+ mbedtls_aes_free(&ctx);
3881+ return ret;
3882+}
3883+
3884+int aes_128_ctr_encrypt(const u8 *key, const u8 *nonce,
3885+ u8 *data, size_t data_len)
3886+{
3887+ return aes_ctr_encrypt(key, 16, nonce, data, data_len);
3888+}
3889+
3890+
3891+/* aes-cbc.c */
3892+static int aes_128_cbc_oper(const u8 *key, const u8 *iv,
3893+ u8 *data, size_t data_len, int mode)
3894+{
3895+ unsigned char ivec[MBEDTLS_AES_BLOCK_SIZE];
3896+ os_memcpy(ivec, iv, MBEDTLS_AES_BLOCK_SIZE); /*(must be writable)*/
3897+
3898+ mbedtls_aes_context ctx;
3899+ mbedtls_aes_init(&ctx);
3900+ int ret = (mode == MBEDTLS_AES_ENCRYPT
3901+ ? mbedtls_aes_setkey_enc(&ctx, key, 128)
3902+ : mbedtls_aes_setkey_dec(&ctx, key, 128))
3903+ || mbedtls_aes_crypt_cbc(&ctx, mode, data_len, ivec, data, data);
3904+ mbedtls_aes_free(&ctx);
3905+ return ret ? -1 : 0;
3906+}
3907+
3908+int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
3909+{
3910+ if (TEST_FAIL())
3911+ return -1;
3912+
3913+ return aes_128_cbc_oper(key, iv, data, data_len, MBEDTLS_AES_ENCRYPT);
3914+}
3915+
3916+int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
3917+{
3918+ if (TEST_FAIL())
3919+ return -1;
3920+
3921+ return aes_128_cbc_oper(key, iv, data, data_len, MBEDTLS_AES_DECRYPT);
3922+}
3923+
3924+
3925+/*
3926+ * Much of the following is documented in crypto.h as for CONFIG_TLS=internal
3927+ * but such comments are not accurate:
3928+ *
3929+ * "This function is only used with internal TLSv1 implementation
3930+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
3931+ * to implement this."
3932+ */
3933+
3934+
3935+#ifdef CRYPTO_MBEDTLS_CRYPTO_CIPHER
3936+
3937+#include <mbedtls/cipher.h>
3938+
3939+struct crypto_cipher
3940+{
3941+ mbedtls_cipher_context_t ctx_enc;
3942+ mbedtls_cipher_context_t ctx_dec;
3943+};
3944+
3945+struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
3946+ const u8 *iv, const u8 *key,
3947+ size_t key_len)
3948+{
3949+ /* IKEv2 src/eap_common/ikev2_common.c:ikev2_{encr,decr}_encrypt()
3950+ * uses one of CRYPTO_CIPHER_ALG_AES or CRYPTO_CIPHER_ALG_3DES */
3951+
3952+ mbedtls_cipher_type_t cipher_type;
3953+ size_t iv_len;
3954+ switch (alg) {
3955+ #ifdef MBEDTLS_ARC4_C
3956+ #if 0
3957+ case CRYPTO_CIPHER_ALG_RC4:
3958+ cipher_type = MBEDTLS_CIPHER_ARC4_128;
3959+ iv_len = 0;
3960+ break;
3961+ #endif
3962+ #endif
3963+ #ifdef MBEDTLS_AES_C
3964+ case CRYPTO_CIPHER_ALG_AES:
3965+ if (key_len == 16) cipher_type = MBEDTLS_CIPHER_AES_128_CTR;
3966+ if (key_len == 24) cipher_type = MBEDTLS_CIPHER_AES_192_CTR;
3967+ if (key_len == 32) cipher_type = MBEDTLS_CIPHER_AES_256_CTR;
3968+ iv_len = 16;
3969+ break;
3970+ #endif
3971+ #ifdef MBEDTLS_DES_C
3972+ case CRYPTO_CIPHER_ALG_3DES:
3973+ cipher_type = MBEDTLS_CIPHER_DES_EDE3_CBC;
3974+ iv_len = 8;
3975+ break;
3976+ #if 0
3977+ case CRYPTO_CIPHER_ALG_DES:
3978+ cipher_type = MBEDTLS_CIPHER_DES_CBC;
3979+ iv_len = 8;
3980+ break;
3981+ #endif
3982+ #endif
3983+ default:
3984+ return NULL;
3985+ }
3986+
3987+ const mbedtls_cipher_info_t *cipher_info;
3988+ cipher_info = mbedtls_cipher_info_from_type(cipher_type);
3989+ if (cipher_info == NULL)
3990+ return NULL;
3991+
3992+ key_len *= 8; /* key_bitlen */
3993+ #if 0 /*(were key_bitlen not already available)*/
3994+ #if MBEDTLS_VERSION_NUMBER >= 0x03010000 /* mbedtls 3.1.0 */
3995+ key_len = mbedtls_cipher_info_get_key_bitlen(cipher_info);
3996+ #else
3997+ key_len = cipher_info->MBEDTLS_PRIVATE(key_bitlen);
3998+ #endif
3999+ #endif
4000+
4001+ #if 0 /*(were iv_len not known above, would need MBEDTLS_PRIVATE(iv_size))*/
4002+ iv_len = cipher_info->MBEDTLS_PRIVATE(iv_size);
4003+ #endif
4004+
4005+ struct crypto_cipher *ctx = os_malloc(sizeof(*ctx));
4006+ if (!ctx)
4007+ return NULL;
4008+
4009+ mbedtls_cipher_init(&ctx->ctx_enc);
4010+ mbedtls_cipher_init(&ctx->ctx_dec);
4011+ if ( mbedtls_cipher_setup(&ctx->ctx_enc,cipher_info) == 0
4012+ && mbedtls_cipher_setup(&ctx->ctx_dec,cipher_info) == 0
4013+ && mbedtls_cipher_setkey(&ctx->ctx_enc,key,key_len,MBEDTLS_ENCRYPT) == 0
4014+ && mbedtls_cipher_setkey(&ctx->ctx_dec,key,key_len,MBEDTLS_DECRYPT) == 0
4015+ && mbedtls_cipher_set_iv(&ctx->ctx_enc,iv,iv_len) == 0
4016+ && mbedtls_cipher_set_iv(&ctx->ctx_dec,iv,iv_len) == 0
4017+ && mbedtls_cipher_reset(&ctx->ctx_enc) == 0
4018+ && mbedtls_cipher_reset(&ctx->ctx_dec) == 0) {
4019+ return ctx;
4020+ }
4021+
4022+ mbedtls_cipher_free(&ctx->ctx_enc);
4023+ mbedtls_cipher_free(&ctx->ctx_dec);
4024+ os_free(ctx);
4025+ return NULL;
4026+}
4027+
4028+int crypto_cipher_encrypt(struct crypto_cipher *ctx,
4029+ const u8 *plain, u8 *crypt, size_t len)
4030+{
4031+ size_t olen = 0; /*(poor interface above; unknown size of u8 *crypt)*/
4032+ return (mbedtls_cipher_update(&ctx->ctx_enc, plain, len, crypt, &olen)
4033+ || mbedtls_cipher_finish(&ctx->ctx_enc, crypt + olen, &olen)) ? -1 : 0;
4034+}
4035+
4036+int crypto_cipher_decrypt(struct crypto_cipher *ctx,
4037+ const u8 *crypt, u8 *plain, size_t len)
4038+{
4039+ size_t olen = 0; /*(poor interface above; unknown size of u8 *plain)*/
4040+ return (mbedtls_cipher_update(&ctx->ctx_dec, crypt, len, plain, &olen)
4041+ || mbedtls_cipher_finish(&ctx->ctx_dec, plain + olen, &olen)) ? -1 : 0;
4042+}
4043+
4044+void crypto_cipher_deinit(struct crypto_cipher *ctx)
4045+{
4046+ mbedtls_cipher_free(&ctx->ctx_enc);
4047+ mbedtls_cipher_free(&ctx->ctx_dec);
4048+ os_free(ctx);
4049+}
4050+
4051+#endif /* CRYPTO_MBEDTLS_CRYPTO_CIPHER */
4052+
4053+
4054+#ifdef CRYPTO_MBEDTLS_CRYPTO_HASH
4055+
4056+struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
4057+ size_t key_len)
4058+{
4059+ mbedtls_md_type_t md_type;
4060+ int is_hmac = 0;
4061+
4062+ switch (alg) {
4063+ #ifdef MBEDTLS_MD5_C
4064+ case CRYPTO_HASH_ALG_MD5:
4065+ md_type = MBEDTLS_MD_MD5;
4066+ break;
4067+ #endif
4068+ #ifdef MBEDTLS_SHA1_C
4069+ case CRYPTO_HASH_ALG_SHA1:
4070+ md_type = MBEDTLS_MD_SHA1;
4071+ break;
4072+ #endif
4073+ #ifdef MBEDTLS_MD5_C
4074+ case CRYPTO_HASH_ALG_HMAC_MD5:
4075+ md_type = MBEDTLS_MD_MD5;
4076+ is_hmac = 1;
4077+ break;
4078+ #endif
4079+ #ifdef MBEDTLS_SHA1_C
4080+ case CRYPTO_HASH_ALG_HMAC_SHA1:
4081+ md_type = MBEDTLS_MD_SHA1;
4082+ is_hmac = 1;
4083+ break;
4084+ #endif
4085+ #ifdef MBEDTLS_SHA256_C
4086+ case CRYPTO_HASH_ALG_SHA256:
4087+ md_type = MBEDTLS_MD_SHA256;
4088+ break;
4089+ case CRYPTO_HASH_ALG_HMAC_SHA256:
4090+ md_type = MBEDTLS_MD_SHA256;
4091+ is_hmac = 1;
4092+ break;
4093+ #endif
4094+ #ifdef MBEDTLS_SHA512_C
4095+ case CRYPTO_HASH_ALG_SHA384:
4096+ md_type = MBEDTLS_MD_SHA384;
4097+ break;
4098+ case CRYPTO_HASH_ALG_SHA512:
4099+ md_type = MBEDTLS_MD_SHA512;
4100+ break;
4101+ #endif
4102+ default:
4103+ return NULL;
4104+ }
4105+
4106+ const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_type);
4107+ if (!md_info)
4108+ return NULL;
4109+
4110+ mbedtls_md_context_t *mctx = os_malloc(sizeof(*mctx));
4111+ if (mctx == NULL)
4112+ return NULL;
4113+
4114+ mbedtls_md_init(mctx);
4115+ if (mbedtls_md_setup(mctx, md_info, is_hmac) != 0) {
4116+ os_free(mctx);
4117+ return NULL;
4118+ }
4119+
4120+ if (is_hmac)
4121+ mbedtls_md_hmac_starts(mctx, key, key_len);
4122+ else
4123+ mbedtls_md_starts(mctx);
4124+ return (struct crypto_hash *)((uintptr_t)mctx | is_hmac);
4125+}
4126+
4127+void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
4128+{
4129+ mbedtls_md_context_t *mctx = (mbedtls_md_context_t*)((uintptr_t)ctx & ~1uL);
4130+ #if 0
4131+ /*(mbedtls_md_hmac_update() and mbedtls_md_update()
4132+ * make same modifications under the hood in mbedtls)*/
4133+ if ((uintptr_t)ctx & 1uL)
4134+ mbedtls_md_hmac_update(mctx, data, len);
4135+ else
4136+ #endif
4137+ mbedtls_md_update(mctx, data, len);
4138+}
4139+
4140+int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
4141+{
4142+ mbedtls_md_context_t *mctx = (mbedtls_md_context_t*)((uintptr_t)ctx & ~1uL);
4143+ if (mac != NULL && len != NULL) { /*(NULL if caller just freeing context)*/
4144+ #if MBEDTLS_VERSION_NUMBER >= 0x03020000 /* mbedtls 3.2.0 */
4145+ const mbedtls_md_info_t *md_info = mbedtls_md_info_from_ctx(mctx);
4146+ #else
4147+ const mbedtls_md_info_t *md_info = mctx->MBEDTLS_PRIVATE(md_info);
4148+ #endif
4149+ size_t maclen = mbedtls_md_get_size(md_info);
4150+ if (*len < maclen) {
4151+ *len = maclen;
4152+ /*(note: ctx not freed; can call again with larger *len)*/
4153+ return -1;
4154+ }
4155+ *len = maclen;
4156+ if ((uintptr_t)ctx & 1uL)
4157+ mbedtls_md_hmac_finish(mctx, mac);
4158+ else
4159+ mbedtls_md_finish(mctx, mac);
4160+ }
4161+ mbedtls_md_free(mctx);
4162+ os_free(mctx);
4163+
4164+ if (TEST_FAIL())
4165+ return -1;
4166+
4167+ return 0;
4168+}
4169+
4170+#endif /* CRYPTO_MBEDTLS_CRYPTO_HASH */
4171+
4172+
4173+#ifdef CRYPTO_MBEDTLS_CRYPTO_BIGNUM
4174+
4175+#include <mbedtls/bignum.h>
4176+
4177+/* crypto.h bignum interfaces */
4178+
4179+struct crypto_bignum *crypto_bignum_init(void)
4180+{
4181+ if (TEST_FAIL())
4182+ return NULL;
4183+
4184+ mbedtls_mpi *bn = os_malloc(sizeof(*bn));
4185+ if (bn)
4186+ mbedtls_mpi_init(bn);
4187+ return (struct crypto_bignum *)bn;
4188+}
4189+
4190+struct crypto_bignum *crypto_bignum_init_set(const u8 *buf, size_t len)
4191+{
4192+ if (TEST_FAIL())
4193+ return NULL;
4194+
4195+ mbedtls_mpi *bn = os_malloc(sizeof(*bn));
4196+ if (bn) {
4197+ mbedtls_mpi_init(bn);
4198+ if (mbedtls_mpi_read_binary(bn, buf, len) == 0)
4199+ return (struct crypto_bignum *)bn;
4200+ }
4201+
4202+ os_free(bn);
4203+ return NULL;
4204+}
4205+
4206+struct crypto_bignum *crypto_bignum_init_uint(unsigned int val)
4207+{
4208+ if (TEST_FAIL())
4209+ return NULL;
4210+
4211+ #if 0 /*(hostap use of this interface passes int, not uint)*/
4212+ val = host_to_be32(val);
4213+ return crypto_bignum_init_set((const u8 *)&val, sizeof(val));
4214+ #else
4215+ mbedtls_mpi *bn = os_malloc(sizeof(*bn));
4216+ if (bn) {
4217+ mbedtls_mpi_init(bn);
4218+ if (mbedtls_mpi_lset(bn, (int)val) == 0)
4219+ return (struct crypto_bignum *)bn;
4220+ }
4221+
4222+ os_free(bn);
4223+ return NULL;
4224+ #endif
4225+}
4226+
4227+void crypto_bignum_deinit(struct crypto_bignum *n, int clear)
4228+{
4229+ mbedtls_mpi_free((mbedtls_mpi *)n);
4230+ os_free(n);
4231+}
4232+
4233+int crypto_bignum_to_bin(const struct crypto_bignum *a,
4234+ u8 *buf, size_t buflen, size_t padlen)
4235+{
4236+ if (TEST_FAIL())
4237+ return -1;
4238+
4239+ size_t n = mbedtls_mpi_size((mbedtls_mpi *)a);
4240+ if (n < padlen)
4241+ n = padlen;
4242+ return n > buflen || mbedtls_mpi_write_binary((mbedtls_mpi *)a, buf, n)
4243+ ? -1
4244+ : (int)(n);
4245+}
4246+
4247+int crypto_bignum_rand(struct crypto_bignum *r, const struct crypto_bignum *m)
4248+{
4249+ if (TEST_FAIL())
4250+ return -1;
4251+
4252+ /*assert(r != m);*//* r must not be same as m for mbedtls_mpi_random()*/
4253+ #if MBEDTLS_VERSION_NUMBER >= 0x021B0000 /* mbedtls 2.27.0 */
4254+ return mbedtls_mpi_random((mbedtls_mpi *)r, 0, (mbedtls_mpi *)m,
4255+ mbedtls_ctr_drbg_random,
4256+ crypto_mbedtls_ctr_drbg()) ? -1 : 0;
4257+ #else
4258+ /* (needed by EAP_PWD, SAE, DPP) */
4259+ wpa_printf(MSG_ERROR,
4260+ "mbedtls 2.27.0 or later required for mbedtls_mpi_random()");
4261+ return -1;
4262+ #endif
4263+}
4264+
4265+int crypto_bignum_add(const struct crypto_bignum *a,
4266+ const struct crypto_bignum *b,
4267+ struct crypto_bignum *c)
4268+{
4269+ return mbedtls_mpi_add_mpi((mbedtls_mpi *)c,
4270+ (const mbedtls_mpi *)a,
4271+ (const mbedtls_mpi *)b) ? -1 : 0;
4272+}
4273+
4274+int crypto_bignum_mod(const struct crypto_bignum *a,
4275+ const struct crypto_bignum *b,
4276+ struct crypto_bignum *c)
4277+{
4278+ return mbedtls_mpi_mod_mpi((mbedtls_mpi *)c,
4279+ (const mbedtls_mpi *)a,
4280+ (const mbedtls_mpi *)b) ? -1 : 0;
4281+}
4282+
4283+int crypto_bignum_exptmod(const struct crypto_bignum *a,
4284+ const struct crypto_bignum *b,
4285+ const struct crypto_bignum *c,
4286+ struct crypto_bignum *d)
4287+{
4288+ if (TEST_FAIL())
4289+ return -1;
4290+
4291+ /* (check if input params match d; d is the result) */
4292+ /* (a == d) is ok in current mbedtls implementation */
4293+ if (b == d || c == d) { /*(not ok; store result in intermediate)*/
4294+ mbedtls_mpi R;
4295+ mbedtls_mpi_init(&R);
4296+ int rc = mbedtls_mpi_exp_mod(&R,
4297+ (const mbedtls_mpi *)a,
4298+ (const mbedtls_mpi *)b,
4299+ (const mbedtls_mpi *)c,
4300+ NULL)
4301+ || mbedtls_mpi_copy((mbedtls_mpi *)d, &R) ? -1 : 0;
4302+ mbedtls_mpi_free(&R);
4303+ return rc;
4304+ }
4305+ else {
4306+ return mbedtls_mpi_exp_mod((mbedtls_mpi *)d,
4307+ (const mbedtls_mpi *)a,
4308+ (const mbedtls_mpi *)b,
4309+ (const mbedtls_mpi *)c,
4310+ NULL) ? -1 : 0;
4311+ }
4312+}
4313+
4314+int crypto_bignum_inverse(const struct crypto_bignum *a,
4315+ const struct crypto_bignum *b,
4316+ struct crypto_bignum *c)
4317+{
4318+ if (TEST_FAIL())
4319+ return -1;
4320+
4321+ return mbedtls_mpi_inv_mod((mbedtls_mpi *)c,
4322+ (const mbedtls_mpi *)a,
4323+ (const mbedtls_mpi *)b) ? -1 : 0;
4324+}
4325+
4326+int crypto_bignum_sub(const struct crypto_bignum *a,
4327+ const struct crypto_bignum *b,
4328+ struct crypto_bignum *c)
4329+{
4330+ if (TEST_FAIL())
4331+ return -1;
4332+
4333+ return mbedtls_mpi_sub_mpi((mbedtls_mpi *)c,
4334+ (const mbedtls_mpi *)a,
4335+ (const mbedtls_mpi *)b) ? -1 : 0;
4336+}
4337+
4338+int crypto_bignum_div(const struct crypto_bignum *a,
4339+ const struct crypto_bignum *b,
4340+ struct crypto_bignum *c)
4341+{
4342+ if (TEST_FAIL())
4343+ return -1;
4344+
4345+ /*(most current use of this crypto.h interface has a == c (result),
4346+ * so store result in an intermediate to avoid overwritten input)*/
4347+ mbedtls_mpi R;
4348+ mbedtls_mpi_init(&R);
4349+ int rc = mbedtls_mpi_div_mpi(&R, NULL,
4350+ (const mbedtls_mpi *)a,
4351+ (const mbedtls_mpi *)b)
4352+ || mbedtls_mpi_copy((mbedtls_mpi *)c, &R) ? -1 : 0;
4353+ mbedtls_mpi_free(&R);
4354+ return rc;
4355+}
4356+
4357+int crypto_bignum_addmod(const struct crypto_bignum *a,
4358+ const struct crypto_bignum *b,
4359+ const struct crypto_bignum *c,
4360+ struct crypto_bignum *d)
4361+{
4362+ if (TEST_FAIL())
4363+ return -1;
4364+
4365+ return mbedtls_mpi_add_mpi((mbedtls_mpi *)d,
4366+ (const mbedtls_mpi *)a,
4367+ (const mbedtls_mpi *)b)
4368+ || mbedtls_mpi_mod_mpi((mbedtls_mpi *)d,
4369+ (mbedtls_mpi *)d,
4370+ (const mbedtls_mpi *)c) ? -1 : 0;
4371+}
4372+
4373+int crypto_bignum_mulmod(const struct crypto_bignum *a,
4374+ const struct crypto_bignum *b,
4375+ const struct crypto_bignum *c,
4376+ struct crypto_bignum *d)
4377+{
4378+ if (TEST_FAIL())
4379+ return -1;
4380+
4381+ return mbedtls_mpi_mul_mpi((mbedtls_mpi *)d,
4382+ (const mbedtls_mpi *)a,
4383+ (const mbedtls_mpi *)b)
4384+ || mbedtls_mpi_mod_mpi((mbedtls_mpi *)d,
4385+ (mbedtls_mpi *)d,
4386+ (const mbedtls_mpi *)c) ? -1 : 0;
4387+}
4388+
4389+int crypto_bignum_sqrmod(const struct crypto_bignum *a,
4390+ const struct crypto_bignum *b,
4391+ struct crypto_bignum *c)
4392+{
4393+ if (TEST_FAIL())
4394+ return -1;
4395+
4396+ #if 1
4397+ return crypto_bignum_mulmod(a, a, b, c);
4398+ #else
4399+ mbedtls_mpi bn;
4400+ mbedtls_mpi_init(&bn);
4401+ if (mbedtls_mpi_lset(&bn, 2)) /* alt?: mbedtls_mpi_set_bit(&bn, 1) */
4402+ return -1;
4403+ int ret = mbedtls_mpi_exp_mod((mbedtls_mpi *)c,
4404+ (const mbedtls_mpi *)a, &bn,
4405+ (const mbedtls_mpi *)b, NULL) ? -1 : 0;
4406+ mbedtls_mpi_free(&bn);
4407+ return ret;
4408+ #endif
4409+}
4410+
4411+int crypto_bignum_rshift(const struct crypto_bignum *a, int n,
4412+ struct crypto_bignum *r)
4413+{
4414+ return mbedtls_mpi_copy((mbedtls_mpi *)r, (const mbedtls_mpi *)a)
4415+ || mbedtls_mpi_shift_r((mbedtls_mpi *)r, n) ? -1 : 0;
4416+}
4417+
4418+int crypto_bignum_cmp(const struct crypto_bignum *a,
4419+ const struct crypto_bignum *b)
4420+{
4421+ return mbedtls_mpi_cmp_mpi((const mbedtls_mpi *)a, (const mbedtls_mpi *)b);
4422+}
4423+
4424+int crypto_bignum_is_zero(const struct crypto_bignum *a)
4425+{
4426+ /* XXX: src/common/sae.c:sswu() contains comment:
4427+ * "TODO: Make sure crypto_bignum_is_zero() is constant time"
4428+ * Note: mbedtls_mpi_cmp_int() *is not* constant time */
4429+ return (mbedtls_mpi_cmp_int((const mbedtls_mpi *)a, 0) == 0);
4430+}
4431+
4432+int crypto_bignum_is_one(const struct crypto_bignum *a)
4433+{
4434+ return (mbedtls_mpi_cmp_int((const mbedtls_mpi *)a, 1) == 0);
4435+}
4436+
4437+int crypto_bignum_is_odd(const struct crypto_bignum *a)
4438+{
4439+ return mbedtls_mpi_get_bit((const mbedtls_mpi *)a, 0);
4440+}
4441+
4442+#include "utils/const_time.h"
4443+int crypto_bignum_legendre(const struct crypto_bignum *a,
4444+ const struct crypto_bignum *p)
4445+{
4446+ if (TEST_FAIL())
4447+ return -2;
4448+
4449+ /* Security Note:
4450+ * mbedtls_mpi_exp_mod() is not documented to run in constant time,
4451+ * though mbedtls/library/bignum.c uses constant_time_internal.h funcs.
4452+ * Compare to crypto_openssl.c:crypto_bignum_legendre()
4453+ * which uses openssl BN_mod_exp_mont_consttime()
4454+ * mbedtls/library/ecp.c has further countermeasures to timing attacks,
4455+ * (but ecp.c funcs are not used here) */
4456+
4457+ mbedtls_mpi exp, tmp;
4458+ mbedtls_mpi_init(&exp);
4459+ mbedtls_mpi_init(&tmp);
4460+
4461+ /* exp = (p-1) / 2 */
4462+ int res;
4463+ if (mbedtls_mpi_sub_int(&exp, (const mbedtls_mpi *)p, 1) == 0
4464+ && mbedtls_mpi_shift_r(&exp, 1) == 0
4465+ && mbedtls_mpi_exp_mod(&tmp, (const mbedtls_mpi *)a, &exp,
4466+ (const mbedtls_mpi *)p, NULL) == 0) {
4467+ /*(modified from crypto_openssl.c:crypto_bignum_legendre())*/
4468+ /* Return 1 if tmp == 1, 0 if tmp == 0, or -1 otherwise. Need
4469+ * to use constant time selection to avoid branches here. */
4470+ unsigned int mask;
4471+ res = -1;
4472+ mask = const_time_eq((mbedtls_mpi_cmp_int(&tmp, 1) == 0), 1);
4473+ res = const_time_select_int(mask, 1, res);
4474+ mask = const_time_eq((mbedtls_mpi_cmp_int(&tmp, 0) == 0), 1);
4475+ res = const_time_select_int(mask, 0, res);
4476+ } else {
4477+ res = -2;
4478+ }
4479+
4480+ mbedtls_mpi_free(&tmp);
4481+ mbedtls_mpi_free(&exp);
4482+ return res;
4483+}
4484+
4485+#endif /* CRYPTO_MBEDTLS_CRYPTO_BIGNUM */
4486+
4487+
4488+#ifdef CRYPTO_MBEDTLS_CRYPTO_DH
4489+
4490+/* crypto_internal-modexp.c */
4491+
4492+#include <mbedtls/bignum.h>
4493+#include <mbedtls/dhm.h>
4494+
4495+#if 0 /* crypto_dh_init() and crypto_dh_derive_secret() prefer to use mbedtls */
4496+int crypto_mod_exp(const u8 *base, size_t base_len,
4497+ const u8 *power, size_t power_len,
4498+ const u8 *modulus, size_t modulus_len,
4499+ u8 *result, size_t *result_len)
4500+{
4501+ if (TEST_FAIL())
4502+ return -1;
4503+
4504+ mbedtls_mpi bn_base, bn_exp, bn_modulus, bn_result;
4505+ mbedtls_mpi_init(&bn_base);
4506+ mbedtls_mpi_init(&bn_exp);
4507+ mbedtls_mpi_init(&bn_modulus);
4508+ mbedtls_mpi_init(&bn_result);
4509+
4510+ size_t len;
4511+ int ret = mbedtls_mpi_read_binary(&bn_base, base, base_len)
4512+ || mbedtls_mpi_read_binary(&bn_exp, power, power_len)
4513+ || mbedtls_mpi_read_binary(&bn_modulus, modulus, modulus_len)
4514+ || mbedtls_mpi_exp_mod(&bn_result,&bn_base,&bn_exp,&bn_modulus,NULL)
4515+ || (len = mbedtls_mpi_size(&bn_result)) > *result_len
4516+ || mbedtls_mpi_write_binary(&bn_result, result, (*result_len = len))
4517+ ? -1
4518+ : 0;
4519+
4520+ mbedtls_mpi_free(&bn_base);
4521+ mbedtls_mpi_free(&bn_exp);
4522+ mbedtls_mpi_free(&bn_modulus);
4523+ mbedtls_mpi_free(&bn_result);
4524+ return ret;
4525+}
4526+#endif
4527+
4528+static int crypto_mbedtls_dh_set_bin_pg(mbedtls_dhm_context *ctx, u8 generator,
4529+ const u8 *prime, size_t prime_len)
4530+{
4531+ /*(could set these directly in MBEDTLS_PRIVATE members)*/
4532+ mbedtls_mpi P, G;
4533+ mbedtls_mpi_init(&P);
4534+ mbedtls_mpi_init(&G);
4535+ int ret = mbedtls_mpi_lset(&G, generator)
4536+ || mbedtls_mpi_read_binary(&P, prime, prime_len)
4537+ || mbedtls_dhm_set_group(ctx, &P, &G);
4538+ mbedtls_mpi_free(&P);
4539+ mbedtls_mpi_free(&G);
4540+ return ret;
4541+}
4542+
4543+__attribute_noinline__
4544+static int crypto_mbedtls_dh_init_public(mbedtls_dhm_context *ctx, u8 generator,
4545+ const u8 *prime, size_t prime_len,
4546+ u8 *privkey, u8 *pubkey)
4547+{
4548+ if (crypto_mbedtls_dh_set_bin_pg(ctx, generator, prime, prime_len)
4549+ || mbedtls_dhm_make_public(ctx, (int)prime_len, pubkey, prime_len,
4550+ mbedtls_ctr_drbg_random,
4551+ crypto_mbedtls_ctr_drbg()))
4552+ return -1;
4553+
4554+ /*(enable later when upstream mbedtls interface changes require)*/
4555+ #if 0 && MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
4556+ mbedtls_mpi X;
4557+ mbedtls_mpi_init(&X);
4558+ int ret = mbedtls_dhm_get_value(ctx, MBEDTLS_DHM_PARAM_X, &X)
4559+ || mbedtls_mpi_write_binary(&X, privkey, prime_len) ? -1 : 0;
4560+ mbedtls_mpi_free(&X);
4561+ return ret;
4562+ #else
4563+ return mbedtls_mpi_write_binary(&ctx->MBEDTLS_PRIVATE(X),
4564+ privkey, prime_len) ? -1 : 0;
4565+ #endif
4566+}
4567+
4568+int crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey,
4569+ u8 *pubkey)
4570+{
4571+ if (TEST_FAIL())
4572+ return -1;
4573+
4574+ #if 0 /*(crypto_dh_init() duplicated (and identical) in crypto_*.c modules)*/
4575+ size_t pubkey_len, pad;
4576+
4577+ if (os_get_random(privkey, prime_len) < 0)
4578+ return -1;
4579+ if (os_memcmp(privkey, prime, prime_len) > 0) {
4580+ /* Make sure private value is smaller than prime */
4581+ privkey[0] = 0;
4582+ }
4583+
4584+ pubkey_len = prime_len;
4585+ if (crypto_mod_exp(&generator, 1, privkey, prime_len, prime, prime_len,
4586+ pubkey, &pubkey_len) < 0)
4587+ return -1;
4588+ if (pubkey_len < prime_len) {
4589+ pad = prime_len - pubkey_len;
4590+ os_memmove(pubkey + pad, pubkey, pubkey_len);
4591+ os_memset(pubkey, 0, pad);
4592+ }
4593+
4594+ return 0;
4595+ #else
4596+ /* Prefer to use mbedtls to derive our public/private key, as doing so
4597+ * leverages mbedtls to properly format output and to perform blinding*/
4598+ mbedtls_dhm_context ctx;
4599+ mbedtls_dhm_init(&ctx);
4600+ int ret = crypto_mbedtls_dh_init_public(&ctx, generator, prime,
4601+ prime_len, privkey, pubkey);
4602+ mbedtls_dhm_free(&ctx);
4603+ return ret;
4604+ #endif
4605+}
4606+
4607+/*(crypto_dh_derive_secret() could be implemented using crypto.h APIs
4608+ * instead of being reimplemented in each crypto_*.c)*/
4609+int crypto_dh_derive_secret(u8 generator, const u8 *prime, size_t prime_len,
4610+ const u8 *order, size_t order_len,
4611+ const u8 *privkey, size_t privkey_len,
4612+ const u8 *pubkey, size_t pubkey_len,
4613+ u8 *secret, size_t *len)
4614+{
4615+ if (TEST_FAIL())
4616+ return -1;
4617+
4618+ #if 0
4619+ if (pubkey_len > prime_len ||
4620+ (pubkey_len == prime_len &&
4621+ os_memcmp(pubkey, prime, prime_len) >= 0))
4622+ return -1;
4623+
4624+ int res = 0;
4625+ mbedtls_mpi pub;
4626+ mbedtls_mpi_init(&pub);
4627+ if (mbedtls_mpi_read_binary(&pub, pubkey, pubkey_len)
4628+ || mbedtls_mpi_cmp_int(&pub, 1) <= 0) {
4629+ res = -1;
4630+ } else if (order) {
4631+ mbedtls_mpi p, q, tmp;
4632+ mbedtls_mpi_init(&p);
4633+ mbedtls_mpi_init(&q);
4634+ mbedtls_mpi_init(&tmp);
4635+
4636+ /* verify: pubkey^q == 1 mod p */
4637+ res = (mbedtls_mpi_read_binary(&p, prime, prime_len)
4638+ || mbedtls_mpi_read_binary(&q, order, order_len)
4639+ || mbedtls_mpi_exp_mod(&tmp, &pub, &q, &p, NULL)
4640+ || mbedtls_mpi_cmp_int(&tmp, 1) != 0);
4641+
4642+ mbedtls_mpi_free(&p);
4643+ mbedtls_mpi_free(&q);
4644+ mbedtls_mpi_free(&tmp);
4645+ }
4646+ mbedtls_mpi_free(&pub);
4647+
4648+ return (res == 0)
4649+ ? crypto_mod_exp(pubkey, pubkey_len, privkey, privkey_len,
4650+ prime, prime_len, secret, len)
4651+ : -1;
4652+ #else
4653+ /* Prefer to use mbedtls to derive DH shared secret, as doing so
4654+ * leverages mbedtls to validate params and to perform blinding.
4655+ *
4656+ * Attempt to reconstitute DH context to derive shared secret
4657+ * (due to limitations of the interface, which ought to pass context).
4658+ * Force provided G (our private key) into context without validation.
4659+ * Regenerating GX (our public key) not needed to derive shared secret.
4660+ */
4661+ /*(older compilers might not support VLAs)*/
4662+ /*unsigned char buf[2+prime_len+2+1+2+pubkey_len];*/
4663+ unsigned char buf[2+MBEDTLS_MPI_MAX_SIZE+2+1+2+MBEDTLS_MPI_MAX_SIZE];
4664+ unsigned char *p = buf + 2 + prime_len;
4665+ if (2+prime_len+2+1+2+pubkey_len > sizeof(buf))
4666+ return -1;
4667+ WPA_PUT_BE16(buf, prime_len); /*(2-byte big-endian size of prime)*/
4668+ p[0] = 0; /*(2-byte big-endian size of generator)*/
4669+ p[1] = 1;
4670+ p[2] = generator;
4671+ WPA_PUT_BE16(p+3, pubkey_len); /*(2-byte big-endian size of pubkey)*/
4672+ os_memcpy(p+5, pubkey, pubkey_len);
4673+ os_memcpy(buf+2, prime, prime_len);
4674+
4675+ mbedtls_dhm_context ctx;
4676+ mbedtls_dhm_init(&ctx);
4677+ p = buf;
4678+ int ret = mbedtls_dhm_read_params(&ctx, &p, p+2+prime_len+5+pubkey_len)
4679+ || mbedtls_mpi_read_binary(&ctx.MBEDTLS_PRIVATE(X),
4680+ privkey, privkey_len)
4681+ || mbedtls_dhm_calc_secret(&ctx, secret, *len, len,
4682+ mbedtls_ctr_drbg_random,
4683+ crypto_mbedtls_ctr_drbg()) ? -1 : 0;
4684+ mbedtls_dhm_free(&ctx);
4685+ return ret;
4686+ #endif
4687+}
4688+
4689+/* dh_group5.c */
4690+
4691+#include "dh_group5.h"
4692+
4693+/* RFC3526_PRIME_1536[] and RFC3526_GENERATOR_1536[] from crypto_wolfssl.c */
4694+
4695+static const unsigned char RFC3526_PRIME_1536[] = {
4696+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
4697+ 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
4698+ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
4699+ 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
4700+ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
4701+ 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
4702+ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
4703+ 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
4704+ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
4705+ 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
4706+ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
4707+ 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
4708+ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
4709+ 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
4710+ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
4711+ 0xCA, 0x23, 0x73, 0x27, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
4712+};
4713+
4714+static const unsigned char RFC3526_GENERATOR_1536[] = {
4715+ 0x02
4716+};
4717+
4718+void * dh5_init(struct wpabuf **priv, struct wpabuf **publ)
4719+{
4720+ const unsigned char * const prime = RFC3526_PRIME_1536;
4721+ const size_t prime_len = sizeof(RFC3526_PRIME_1536);
4722+ const u8 generator = *RFC3526_GENERATOR_1536;
4723+ struct wpabuf *wpubl = NULL, *wpriv = NULL;
4724+
4725+ mbedtls_dhm_context *ctx = os_malloc(sizeof(*ctx));
4726+ if (ctx == NULL)
4727+ return NULL;
4728+ mbedtls_dhm_init(ctx);
4729+
4730+ if ( (wpubl = wpabuf_alloc(prime_len))
4731+ && (wpriv = wpabuf_alloc(prime_len))
4732+ && crypto_mbedtls_dh_init_public(ctx, generator, prime, prime_len,
4733+ wpabuf_put(wpriv, prime_len),
4734+ wpabuf_put(wpubl, prime_len))==0) {
4735+ wpabuf_free(*publ);
4736+ wpabuf_clear_free(*priv);
4737+ *publ = wpubl;
4738+ *priv = wpriv;
4739+ return ctx;
4740+ }
4741+
4742+ wpabuf_clear_free(wpriv);
4743+ wpabuf_free(wpubl);
4744+ mbedtls_dhm_free(ctx);
4745+ os_free(ctx);
4746+ return NULL;
4747+}
4748+
4749+#ifdef CRYPTO_MBEDTLS_DH5_INIT_FIXED
4750+void * dh5_init_fixed(const struct wpabuf *priv, const struct wpabuf *publ)
4751+{
4752+ const unsigned char * const prime = RFC3526_PRIME_1536;
4753+ const size_t prime_len = sizeof(RFC3526_PRIME_1536);
4754+ const u8 generator = *RFC3526_GENERATOR_1536;
4755+
4756+ mbedtls_dhm_context *ctx = os_malloc(sizeof(*ctx));
4757+ if (ctx == NULL)
4758+ return NULL;
4759+ mbedtls_dhm_init(ctx);
4760+
4761+ if (crypto_mbedtls_dh_set_bin_pg(ctx, generator, prime, prime_len)==0
4762+ #if 0 /*(ignore; not required to derive shared secret)*/
4763+ && mbedtls_mpi_read_binary(&ctx->MBEDTLS_PRIVATE(GX),
4764+ wpabuf_head(publ),wpabuf_len(publ))==0
4765+ #endif
4766+ && mbedtls_mpi_read_binary(&ctx->MBEDTLS_PRIVATE(X),
4767+ wpabuf_head(priv),wpabuf_len(priv))==0) {
4768+ return ctx;
4769+ }
4770+
4771+ mbedtls_dhm_free(ctx);
4772+ os_free(ctx);
4773+ return NULL;
4774+}
4775+#endif
4776+
4777+struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public,
4778+ const struct wpabuf *own_private)
4779+{
4780+ /*((mbedtls_dhm_context *)ctx must already contain own_private)*/
4781+ /* mbedtls 2.x: prime_len = ctx->len; */
4782+ /* mbedtls 3.x: prime_len = mbedtls_dhm_get_len(ctx); */
4783+ size_t olen = sizeof(RFC3526_PRIME_1536); /*(sizeof(); prime known)*/
4784+ struct wpabuf *buf = wpabuf_alloc(olen);
4785+ if (buf == NULL)
4786+ return NULL;
4787+ if (mbedtls_dhm_read_public((mbedtls_dhm_context *)ctx,
4788+ wpabuf_head(peer_public),
4789+ wpabuf_len(peer_public)) == 0
4790+ && mbedtls_dhm_calc_secret(ctx, wpabuf_mhead(buf), olen, &olen,
4791+ mbedtls_ctr_drbg_random,
4792+ crypto_mbedtls_ctr_drbg()) == 0) {
4793+ wpabuf_put(buf, olen);
4794+ return buf;
4795+ }
4796+
4797+ wpabuf_free(buf);
4798+ return NULL;
4799+}
4800+
4801+void dh5_free(void *ctx)
4802+{
4803+ mbedtls_dhm_free(ctx);
4804+ os_free(ctx);
4805+}
4806+
4807+#endif /* CRYPTO_MBEDTLS_CRYPTO_DH */
4808+
4809+
4810+#if defined(CRYPTO_MBEDTLS_CRYPTO_ECDH) || defined(CRYPTO_MBEDTLS_CRYPTO_EC)
4811+
4812+#include <mbedtls/ecp.h>
4813+
4814+#define CRYPTO_EC_pbits(e) (((mbedtls_ecp_group *)(e))->pbits)
4815+#define CRYPTO_EC_plen(e) ((((mbedtls_ecp_group *)(e))->pbits+7)>>3)
4816+#define CRYPTO_EC_P(e) (&((mbedtls_ecp_group *)(e))->P)
4817+#define CRYPTO_EC_N(e) (&((mbedtls_ecp_group *)(e))->N)
4818+#define CRYPTO_EC_A(e) (&((mbedtls_ecp_group *)(e))->A)
4819+#define CRYPTO_EC_B(e) (&((mbedtls_ecp_group *)(e))->B)
4820+#define CRYPTO_EC_G(e) (&((mbedtls_ecp_group *)(e))->G)
4821+
4822+static mbedtls_ecp_group_id crypto_mbedtls_ecp_group_id_from_ike_id(int group)
4823+{
4824+ /* https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml */
4825+ switch (group) {
4826+ #ifdef MBEDTLS_ECP_DP_SECP256R1_ENABLED
4827+ case 19: return MBEDTLS_ECP_DP_SECP256R1;
4828+ #endif
4829+ #ifdef MBEDTLS_ECP_DP_SECP384R1_ENABLED
4830+ case 20: return MBEDTLS_ECP_DP_SECP384R1;
4831+ #endif
4832+ #ifdef MBEDTLS_ECP_DP_SECP521R1_ENABLED
4833+ case 21: return MBEDTLS_ECP_DP_SECP521R1;
4834+ #endif
4835+ #ifdef MBEDTLS_ECP_DP_SECP192R1_ENABLED
4836+ case 25: return MBEDTLS_ECP_DP_SECP192R1;
4837+ #endif
4838+ #ifdef MBEDTLS_ECP_DP_SECP224R1_ENABLED
4839+ case 26: return MBEDTLS_ECP_DP_SECP224R1;
4840+ #endif
4841+ #ifdef MBEDTLS_ECP_DP_BP256R1_ENABLED
4842+ case 28: return MBEDTLS_ECP_DP_BP256R1;
4843+ #endif
4844+ #ifdef MBEDTLS_ECP_DP_BP384R1_ENABLED
4845+ case 29: return MBEDTLS_ECP_DP_BP384R1;
4846+ #endif
4847+ #ifdef MBEDTLS_ECP_DP_BP512R1_ENABLED
4848+ case 30: return MBEDTLS_ECP_DP_BP512R1;
4849+ #endif
4850+ #ifdef MBEDTLS_ECP_DP_CURVE25519_ENABLED
4851+ case 31: return MBEDTLS_ECP_DP_CURVE25519;
4852+ #endif
4853+ #ifdef MBEDTLS_ECP_DP_CURVE448_ENABLED
4854+ case 32: return MBEDTLS_ECP_DP_CURVE448;
4855+ #endif
4856+ default: return MBEDTLS_ECP_DP_NONE;
4857+ }
4858+}
4859+
4860+#ifdef CRYPTO_MBEDTLS_CRYPTO_EC
4861+static int crypto_mbedtls_ike_id_from_ecp_group_id(mbedtls_ecp_group_id grp_id)
4862+{
4863+ /* https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml */
4864+ /*(for crypto_ec_key_group())*/
4865+ switch (grp_id) {
4866+ #ifdef MBEDTLS_ECP_DP_SECP256R1_ENABLED
4867+ case MBEDTLS_ECP_DP_SECP256R1: return 19;
4868+ #endif
4869+ #ifdef MBEDTLS_ECP_DP_SECP384R1_ENABLED
4870+ case MBEDTLS_ECP_DP_SECP384R1: return 20;
4871+ #endif
4872+ #ifdef MBEDTLS_ECP_DP_SECP521R1_ENABLED
4873+ case MBEDTLS_ECP_DP_SECP521R1: return 21;
4874+ #endif
4875+ #ifdef MBEDTLS_ECP_DP_SECP192R1_ENABLED
4876+ case MBEDTLS_ECP_DP_SECP192R1: return 25;
4877+ #endif
4878+ #ifdef MBEDTLS_ECP_DP_SECP224R1_ENABLED
4879+ case MBEDTLS_ECP_DP_SECP224R1: return 26;
4880+ #endif
4881+ #ifdef MBEDTLS_ECP_DP_BP256R1_ENABLED
4882+ case MBEDTLS_ECP_DP_BP256R1: return 28;
4883+ #endif
4884+ #ifdef MBEDTLS_ECP_DP_BP384R1_ENABLED
4885+ case MBEDTLS_ECP_DP_BP384R1: return 29;
4886+ #endif
4887+ #ifdef MBEDTLS_ECP_DP_BP512R1_ENABLED
4888+ case MBEDTLS_ECP_DP_BP512R1: return 30;
4889+ #endif
4890+ #ifdef MBEDTLS_ECP_DP_CURVE25519_ENABLED
4891+ case MBEDTLS_ECP_DP_CURVE25519: return 31;
4892+ #endif
4893+ #ifdef MBEDTLS_ECP_DP_CURVE448_ENABLED
4894+ case MBEDTLS_ECP_DP_CURVE448: return 32;
4895+ #endif
4896+ default: return -1;
4897+ }
4898+}
4899+#endif
4900+
4901+#endif /* CRYPTO_MBEDTLS_CRYPTO_ECDH || CRYPTO_MBEDTLS_CRYPTO_EC */
4902+
4903+
4904+#if defined(CRYPTO_MBEDTLS_CRYPTO_ECDH) || defined(CRYPTO_MBEDTLS_CRYPTO_EC_DPP)
4905+
4906+#include <mbedtls/ecp.h>
4907+#include <mbedtls/pk.h>
4908+
4909+static int crypto_mbedtls_keypair_gen(int group, mbedtls_pk_context *pk)
4910+{
4911+ mbedtls_ecp_group_id grp_id =
4912+ crypto_mbedtls_ecp_group_id_from_ike_id(group);
4913+ if (grp_id == MBEDTLS_ECP_DP_NONE)
4914+ return -1;
4915+ const mbedtls_pk_info_t *pk_info =
4916+ mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
4917+ if (pk_info == NULL)
4918+ return -1;
4919+ return mbedtls_pk_setup(pk, pk_info)
4920+ || mbedtls_ecp_gen_key(grp_id, mbedtls_pk_ec(*pk),
4921+ mbedtls_ctr_drbg_random,
4922+ crypto_mbedtls_ctr_drbg()) ? -1 : 0;
4923+}
4924+
4925+#endif
4926+
4927+
4928+#ifdef CRYPTO_MBEDTLS_CRYPTO_ECDH
4929+
4930+#include <mbedtls/ecdh.h>
4931+#include <mbedtls/ecdsa.h>
4932+#include <mbedtls/ecp.h>
4933+#include <mbedtls/pk.h>
4934+
4935+/* wrap mbedtls_ecdh_context for more future-proof direct access to components
4936+ * (mbedtls_ecdh_context internal implementation may change between releases)
4937+ *
4938+ * If mbedtls_pk_context -- specifically underlying mbedtls_ecp_keypair --
4939+ * lifetime were guaranteed to be longer than that of mbedtls_ecdh_context,
4940+ * then mbedtls_pk_context or mbedtls_ecp_keypair could be stored in crypto_ecdh
4941+ * (or crypto_ec_key could be stored in crypto_ecdh, and crypto_ec_key could
4942+ * wrap mbedtls_ecp_keypair and components, to avoid MBEDTLS_PRIVATE access) */
4943+struct crypto_ecdh {
4944+ mbedtls_ecdh_context ctx;
4945+ mbedtls_ecp_group grp;
4946+ mbedtls_ecp_point Q;
4947+};
4948+
4949+struct crypto_ecdh * crypto_ecdh_init(int group)
4950+{
4951+ mbedtls_pk_context pk;
4952+ mbedtls_pk_init(&pk);
4953+ struct crypto_ecdh *ecdh = crypto_mbedtls_keypair_gen(group, &pk) == 0
4954+ ? crypto_ecdh_init2(group, (struct crypto_ec_key *)&pk)
4955+ : NULL;
4956+ mbedtls_pk_free(&pk);
4957+ return ecdh;
4958+}
4959+
4960+struct crypto_ecdh * crypto_ecdh_init2(int group,
4961+ struct crypto_ec_key *own_key)
4962+{
4963+ mbedtls_ecp_group_id grp_id =
4964+ crypto_mbedtls_ecp_group_id_from_ike_id(group);
4965+ if (grp_id == MBEDTLS_ECP_DP_NONE)
4966+ return NULL;
4967+ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)own_key);
4968+ struct crypto_ecdh *ecdh = os_malloc(sizeof(*ecdh));
4969+ if (ecdh == NULL)
4970+ return NULL;
4971+ mbedtls_ecdh_init(&ecdh->ctx);
4972+ mbedtls_ecp_group_init(&ecdh->grp);
4973+ mbedtls_ecp_point_init(&ecdh->Q);
4974+ if (mbedtls_ecdh_setup(&ecdh->ctx, grp_id) == 0
4975+ && mbedtls_ecdh_get_params(&ecdh->ctx,ecp_kp,MBEDTLS_ECDH_OURS) == 0) {
4976+ /* copy grp and Q for later use
4977+ * (retrieving this info later is more convoluted
4978+ * even if mbedtls_ecdh_make_public() is considered)*/
4979+ #if MBEDTLS_VERSION_NUMBER >= 0x03020000 /* mbedtls 3.2.0 */
4980+ mbedtls_mpi d;
4981+ mbedtls_mpi_init(&d);
4982+ if (mbedtls_ecp_export(ecp_kp, &ecdh->grp, &d, &ecdh->Q) == 0) {
4983+ mbedtls_mpi_free(&d);
4984+ return ecdh;
4985+ }
4986+ mbedtls_mpi_free(&d);
4987+ #else
4988+ if (mbedtls_ecp_group_load(&ecdh->grp, grp_id) == 0
4989+ && mbedtls_ecp_copy(&ecdh->Q, &ecp_kp->MBEDTLS_PRIVATE(Q)) == 0)
4990+ return ecdh;
4991+ #endif
4992+ }
4993+
4994+ mbedtls_ecp_point_free(&ecdh->Q);
4995+ mbedtls_ecp_group_free(&ecdh->grp);
4996+ mbedtls_ecdh_free(&ecdh->ctx);
4997+ os_free(ecdh);
4998+ return NULL;
4999+}
5000+
5001+struct wpabuf * crypto_ecdh_get_pubkey(struct crypto_ecdh *ecdh, int inc_y)
5002+{
5003+ mbedtls_ecp_group *grp = &ecdh->grp;
5004+ size_t prime_len = CRYPTO_EC_plen(grp);
5005+ size_t output_len = prime_len;
5006+ u8 output_offset = 0;
5007+ u8 buf[256];
5008+
5009+ #ifdef MBEDTLS_ECP_MONTGOMERY_ENABLED
5010+ /* len */
5011+ #endif
5012+ #ifdef MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED
5013+ if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {
5014+ output_len = inc_y ? prime_len * 2 + 1 : prime_len + 1;
5015+ output_offset = 1;
5016+ }
5017+ #endif
5018+
5019+ if (output_len > sizeof(buf))
5020+ return NULL;
5021+
5022+ inc_y = inc_y ? MBEDTLS_ECP_PF_UNCOMPRESSED : MBEDTLS_ECP_PF_COMPRESSED;
5023+ if (mbedtls_ecp_point_write_binary(grp, &ecdh->Q, inc_y, &output_len,
5024+ buf, output_len) == 0) {
5025+ return wpabuf_alloc_copy(buf + output_offset, output_len - output_offset);
5026+ }
5027+
5028+ return NULL;
5029+}
5030+
5031+#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
5032+static int crypto_mbedtls_short_weierstrass_derive_y(mbedtls_ecp_group *grp,
5033+ mbedtls_mpi *bn,
5034+ int parity_bit)
5035+{
5036+ /* y^2 = x^3 + ax + b
5037+ * sqrt(w) = w^((p+1)/4) mod p (for prime p where p = 3 mod 4) */
5038+ mbedtls_mpi *cy2 = (mbedtls_mpi *)
5039+ crypto_ec_point_compute_y_sqr((struct crypto_ec *)grp,
5040+ (const struct crypto_bignum *)bn); /*x*/
5041+ if (cy2 == NULL)
5042+ return -1;
5043+
5044+ /*mbedtls_mpi_free(bn);*/
5045+ /*(reuse bn to store result (y))*/
5046+
5047+ mbedtls_mpi exp;
5048+ mbedtls_mpi_init(&exp);
5049+ int ret = mbedtls_mpi_get_bit(&grp->P, 0) != 1 /*(p = 3 mod 4)*/
5050+ || mbedtls_mpi_get_bit(&grp->P, 1) != 1 /*(p = 3 mod 4)*/
5051+ || mbedtls_mpi_add_int(&exp, &grp->P, 1)
5052+ || mbedtls_mpi_shift_r(&exp, 2)
5053+ || mbedtls_mpi_exp_mod(bn, cy2, &exp, &grp->P, NULL)
5054+ || (mbedtls_mpi_get_bit(bn, 0) != parity_bit
5055+ && mbedtls_mpi_sub_mpi(bn, &grp->P, bn));
5056+ mbedtls_mpi_free(&exp);
5057+ mbedtls_mpi_free(cy2);
5058+ os_free(cy2);
5059+ return ret;
5060+}
5061+#endif
5062+
5063+struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y,
5064+ const u8 *key, size_t len)
5065+{
5066+ if (len == 0) /*(invalid peer key)*/
5067+ return NULL;
5068+
5069+ mbedtls_ecp_group *grp = &ecdh->grp;
5070+
5071+ #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
5072+ if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {
5073+ /* add header for mbedtls_ecdh_read_public() */
5074+ u8 buf[256];
5075+ if (sizeof(buf)-1 < len)
5076+ return NULL;
5077+ buf[0] = (u8)(len);
5078+ os_memcpy(buf+1, key, len);
5079+
5080+ if (inc_y) {
5081+ if (!(len & 1)) { /*(dpp code/tests does not include tag?!?)*/
5082+ if (sizeof(buf)-2 < len)
5083+ return NULL;
5084+ buf[0] = (u8)(1+len);
5085+ buf[1] = 0x04;
5086+ os_memcpy(buf+2, key, len);
5087+ }
5088+ len >>= 1; /*(repurpose len to prime_len)*/
5089+ } else { /* (inc_y == 0) */
5090+ /* mbedtls_ecp_point_read_binary() does not currently support
5091+ * MBEDTLS_ECP_PF_COMPRESSED format (buf[1] = 0x02 or 0x03)
5092+ * (returns MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) */
5093+
5094+ /* derive y, amend buf[] with y for UNCOMPRESSED format */
5095+ if (sizeof(buf)-2 < len*2 || len == 0)
5096+ return NULL;
5097+
5098+ buf[0] = (u8)(1+len*2);
5099+ buf[1] = 0x04;
5100+ os_memcpy(buf+2, key, len);
5101+
5102+ mbedtls_mpi bn;
5103+ mbedtls_mpi_init(&bn);
5104+ int ret = mbedtls_mpi_read_binary(&bn, key, len)
5105+ || crypto_mbedtls_short_weierstrass_derive_y(grp, &bn, 0)
5106+ || mbedtls_mpi_write_binary(&bn, buf+2+len, len);
5107+ mbedtls_mpi_free(&bn);
5108+ if (ret != 0)
5109+ return NULL;
5110+ }
5111+
5112+ if (mbedtls_ecdh_read_public(&ecdh->ctx, buf, buf[0]+1))
5113+ return NULL;
5114+ }
5115+ #endif
5116+ #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
5117+ if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {
5118+ if (mbedtls_ecdh_read_public(&ecdh->ctx, key, len))
5119+ return NULL;
5120+ }
5121+ #endif
5122+
5123+ struct wpabuf *buf = wpabuf_alloc(len);
5124+ if (buf == NULL)
5125+ return NULL;
5126+
5127+ if (mbedtls_ecdh_calc_secret(&ecdh->ctx, &len,
5128+ wpabuf_mhead(buf), len,
5129+ mbedtls_ctr_drbg_random,
5130+ crypto_mbedtls_ctr_drbg()) == 0) {
5131+ wpabuf_put(buf, len);
5132+ return buf;
5133+ }
5134+
5135+ wpabuf_clear_free(buf);
5136+ return NULL;
5137+}
5138+
5139+void crypto_ecdh_deinit(struct crypto_ecdh *ecdh)
5140+{
5141+ if (ecdh == NULL)
5142+ return;
5143+ mbedtls_ecp_point_free(&ecdh->Q);
5144+ mbedtls_ecp_group_free(&ecdh->grp);
5145+ mbedtls_ecdh_free(&ecdh->ctx);
5146+ os_free(ecdh);
5147+}
5148+
5149+size_t crypto_ecdh_prime_len(struct crypto_ecdh *ecdh)
5150+{
5151+ return CRYPTO_EC_plen(&ecdh->grp);
5152+}
5153+
5154+#endif /* CRYPTO_MBEDTLS_CRYPTO_ECDH */
5155+
5156+
5157+#ifdef CRYPTO_MBEDTLS_CRYPTO_EC
5158+
5159+#include <mbedtls/ecp.h>
5160+
5161+struct crypto_ec *crypto_ec_init(int group)
5162+{
5163+ mbedtls_ecp_group_id grp_id =
5164+ crypto_mbedtls_ecp_group_id_from_ike_id(group);
5165+ if (grp_id == MBEDTLS_ECP_DP_NONE)
5166+ return NULL;
5167+ mbedtls_ecp_group *e = os_malloc(sizeof(*e));
5168+ if (e == NULL)
5169+ return NULL;
5170+ mbedtls_ecp_group_init(e);
5171+ if (mbedtls_ecp_group_load(e, grp_id) == 0)
5172+ return (struct crypto_ec *)e;
5173+
5174+ mbedtls_ecp_group_free(e);
5175+ os_free(e);
5176+ return NULL;
5177+}
5178+
5179+void crypto_ec_deinit(struct crypto_ec *e)
5180+{
5181+ mbedtls_ecp_group_free((mbedtls_ecp_group *)e);
5182+ os_free(e);
5183+}
5184+
5185+size_t crypto_ec_prime_len(struct crypto_ec *e)
5186+{
5187+ return CRYPTO_EC_plen(e);
5188+}
5189+
5190+size_t crypto_ec_prime_len_bits(struct crypto_ec *e)
5191+{
5192+ return CRYPTO_EC_pbits(e);
5193+}
5194+
5195+size_t crypto_ec_order_len(struct crypto_ec *e)
5196+{
5197+ return (mbedtls_mpi_bitlen(CRYPTO_EC_N(e)) + 7) / 8;
5198+}
5199+
5200+const struct crypto_bignum *crypto_ec_get_prime(struct crypto_ec *e)
5201+{
5202+ return (const struct crypto_bignum *)CRYPTO_EC_P(e);
5203+}
5204+
5205+const struct crypto_bignum *crypto_ec_get_order(struct crypto_ec *e)
5206+{
5207+ return (const struct crypto_bignum *)CRYPTO_EC_N(e);
5208+}
5209+
5210+const struct crypto_bignum *crypto_ec_get_a(struct crypto_ec *e)
5211+{
5212+ static const uint8_t secp256r1_a[] =
5213+ {0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x01,
5214+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
5215+ 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,
5216+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc};
5217+ static const uint8_t secp384r1_a[] =
5218+ {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
5219+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
5220+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
5221+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,
5222+ 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,
5223+ 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xfc};
5224+ static const uint8_t secp521r1_a[] =
5225+ {0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
5226+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
5227+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
5228+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
5229+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
5230+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
5231+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
5232+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
5233+ 0xff,0xfc};
5234+ static const uint8_t secp192r1_a[] =
5235+ {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
5236+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,
5237+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc};
5238+ static const uint8_t secp224r1_a[] =
5239+ {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
5240+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,
5241+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
5242+ 0xff,0xff,0xff,0xfe};
5243+
5244+ const uint8_t *bin = NULL;
5245+ size_t len = 0;
5246+
5247+ /* (mbedtls groups matching supported sswu_curve_param() IKE groups) */
5248+ switch (((mbedtls_ecp_group *)e)->id) {
5249+ #ifdef MBEDTLS_ECP_DP_SECP256R1_ENABLED
5250+ case MBEDTLS_ECP_DP_SECP256R1:
5251+ bin = secp256r1_a;
5252+ len = sizeof(secp256r1_a);
5253+ break;
5254+ #endif
5255+ #ifdef MBEDTLS_ECP_DP_SECP384R1_ENABLED
5256+ case MBEDTLS_ECP_DP_SECP384R1:
5257+ bin = secp384r1_a;
5258+ len = sizeof(secp384r1_a);
5259+ break;
5260+ #endif
5261+ #ifdef MBEDTLS_ECP_DP_SECP521R1_ENABLED
5262+ case MBEDTLS_ECP_DP_SECP521R1:
5263+ bin = secp521r1_a;
5264+ len = sizeof(secp521r1_a);
5265+ break;
5266+ #endif
5267+ #ifdef MBEDTLS_ECP_DP_SECP192R1_ENABLED
5268+ case MBEDTLS_ECP_DP_SECP192R1:
5269+ bin = secp192r1_a;
5270+ len = sizeof(secp192r1_a);
5271+ break;
5272+ #endif
5273+ #ifdef MBEDTLS_ECP_DP_SECP224R1_ENABLED
5274+ case MBEDTLS_ECP_DP_SECP224R1:
5275+ bin = secp224r1_a;
5276+ len = sizeof(secp224r1_a);
5277+ break;
5278+ #endif
5279+ #ifdef MBEDTLS_ECP_DP_BP256R1_ENABLED
5280+ case MBEDTLS_ECP_DP_BP256R1:
5281+ return (const struct crypto_bignum *)CRYPTO_EC_A(e);
5282+ #endif
5283+ #ifdef MBEDTLS_ECP_DP_BP384R1_ENABLED
5284+ case MBEDTLS_ECP_DP_BP384R1:
5285+ return (const struct crypto_bignum *)CRYPTO_EC_A(e);
5286+ #endif
5287+ #ifdef MBEDTLS_ECP_DP_BP512R1_ENABLED
5288+ case MBEDTLS_ECP_DP_BP512R1:
5289+ return (const struct crypto_bignum *)CRYPTO_EC_A(e);
5290+ #endif
5291+ #ifdef MBEDTLS_ECP_DP_CURVE25519_ENABLED
5292+ case MBEDTLS_ECP_DP_CURVE25519:
5293+ return (const struct crypto_bignum *)CRYPTO_EC_A(e);
5294+ #endif
5295+ #ifdef MBEDTLS_ECP_DP_CURVE448_ENABLED
5296+ case MBEDTLS_ECP_DP_CURVE448:
5297+ return (const struct crypto_bignum *)CRYPTO_EC_A(e);
5298+ #endif
5299+ default:
5300+ return NULL;
5301+ }
5302+
5303+ /*(note: not thread-safe; returns file-scoped static storage)*/
5304+ if (mbedtls_mpi_read_binary(&mpi_sw_A, bin, len) == 0)
5305+ return (const struct crypto_bignum *)&mpi_sw_A;
5306+ return NULL;
5307+}
5308+
5309+const struct crypto_bignum *crypto_ec_get_b(struct crypto_ec *e)
5310+{
5311+ return (const struct crypto_bignum *)CRYPTO_EC_B(e);
5312+}
5313+
5314+const struct crypto_ec_point * crypto_ec_get_generator(struct crypto_ec *e)
5315+{
5316+ return (const struct crypto_ec_point *)CRYPTO_EC_G(e);
5317+}
5318+
5319+struct crypto_ec_point *crypto_ec_point_init(struct crypto_ec *e)
5320+{
5321+ if (TEST_FAIL())
5322+ return NULL;
5323+
5324+ mbedtls_ecp_point *p = os_malloc(sizeof(*p));
5325+ if (p != NULL)
5326+ mbedtls_ecp_point_init(p);
5327+ return (struct crypto_ec_point *)p;
5328+}
5329+
5330+void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear)
5331+{
5332+ mbedtls_ecp_point_free((mbedtls_ecp_point *)p);
5333+ os_free(p);
5334+}
5335+
5336+int crypto_ec_point_x(struct crypto_ec *e, const struct crypto_ec_point *p,
5337+ struct crypto_bignum *x)
5338+{
5339+ mbedtls_mpi *px = &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(X);
5340+ return mbedtls_mpi_copy((mbedtls_mpi *)x, px)
5341+ ? -1
5342+ : 0;
5343+}
5344+
5345+int crypto_ec_point_to_bin(struct crypto_ec *e,
5346+ const struct crypto_ec_point *point, u8 *x, u8 *y)
5347+{
5348+ if (TEST_FAIL())
5349+ return -1;
5350+
5351+ /* crypto.h documents crypto_ec_point_to_bin() output is big-endian */
5352+ size_t len = CRYPTO_EC_plen(e);
5353+ if (x) {
5354+ mbedtls_mpi *px = &((mbedtls_ecp_point *)point)->MBEDTLS_PRIVATE(X);
5355+ if (mbedtls_mpi_write_binary(px, x, len))
5356+ return -1;
5357+ }
5358+ if (y) {
5359+ #if 0 /*(should not be necessary; py mpi should be in initial state)*/
5360+ #ifdef MBEDTLS_ECP_MONTGOMERY_ENABLED
5361+ if (mbedtls_ecp_get_type((mbedtls_ecp_group *)e)
5362+ == MBEDTLS_ECP_TYPE_MONTGOMERY) {
5363+ os_memset(y, 0, len);
5364+ return 0;
5365+ }
5366+ #endif
5367+ #endif
5368+ mbedtls_mpi *py = &((mbedtls_ecp_point *)point)->MBEDTLS_PRIVATE(Y);
5369+ if (mbedtls_mpi_write_binary(py, y, len))
5370+ return -1;
5371+ }
5372+ return 0;
5373+}
5374+
5375+struct crypto_ec_point * crypto_ec_point_from_bin(struct crypto_ec *e,
5376+ const u8 *val)
5377+{
5378+ if (TEST_FAIL())
5379+ return NULL;
5380+
5381+ size_t len = CRYPTO_EC_plen(e);
5382+ mbedtls_ecp_point *p = os_malloc(sizeof(*p));
5383+ u8 buf[1+MBEDTLS_MPI_MAX_SIZE*2];
5384+ if (p == NULL)
5385+ return NULL;
5386+ mbedtls_ecp_point_init(p);
5387+
5388+ #ifdef MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED
5389+ if (mbedtls_ecp_get_type((mbedtls_ecp_group *)e)
5390+ == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {
5391+ #if 0 /* prefer alternative to MBEDTLS_PRIVATE() access */
5392+ mbedtls_mpi *px = &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(X);
5393+ mbedtls_mpi *py = &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Y);
5394+ mbedtls_mpi *pz = &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Z);
5395+
5396+ if (mbedtls_mpi_read_binary(px, val, len) == 0
5397+ && mbedtls_mpi_read_binary(py, val + len, len) == 0
5398+ && mbedtls_mpi_lset(pz, 1) == 0)
5399+ return (struct crypto_ec_point *)p;
5400+ #else
5401+ buf[0] = 0x04;
5402+ os_memcpy(buf+1, val, len*2);
5403+ if (mbedtls_ecp_point_read_binary((mbedtls_ecp_group *)e, p,
5404+ buf, 1+len*2) == 0)
5405+ return (struct crypto_ec_point *)p;
5406+ #endif
5407+ }
5408+ #endif
5409+ #ifdef MBEDTLS_ECP_MONTGOMERY_ENABLED
5410+ if (mbedtls_ecp_get_type((mbedtls_ecp_group *)e)
5411+ == MBEDTLS_ECP_TYPE_MONTGOMERY) {
5412+ /* crypto.h interface documents crypto_ec_point_from_bin()
5413+ * val is length: prime_len * 2 and is big-endian
5414+ * (Short Weierstrass is assumed by hostap)
5415+ * Reverse to little-endian format for Montgomery */
5416+ for (unsigned int i = 0; i < len; ++i)
5417+ buf[i] = val[len-1-i];
5418+ if (mbedtls_ecp_point_read_binary((mbedtls_ecp_group *)e, p,
5419+ buf, len) == 0)
5420+ return (struct crypto_ec_point *)p;
5421+ }
5422+ #endif
5423+
5424+ mbedtls_ecp_point_free(p);
5425+ os_free(p);
5426+ return NULL;
5427+}
5428+
5429+int crypto_ec_point_add(struct crypto_ec *e, const struct crypto_ec_point *a,
5430+ const struct crypto_ec_point *b,
5431+ struct crypto_ec_point *c)
5432+{
5433+ if (TEST_FAIL())
5434+ return -1;
5435+
5436+ /* mbedtls does not provide an mbedtls_ecp_point add function */
5437+ mbedtls_mpi one;
5438+ mbedtls_mpi_init(&one);
5439+ int ret = mbedtls_mpi_lset(&one, 1)
5440+ || mbedtls_ecp_muladd(
5441+ (mbedtls_ecp_group *)e, (mbedtls_ecp_point *)c,
5442+ &one, (const mbedtls_ecp_point *)a,
5443+ &one, (const mbedtls_ecp_point *)b) ? -1 : 0;
5444+ mbedtls_mpi_free(&one);
5445+ return ret;
5446+}
5447+
5448+int crypto_ec_point_mul(struct crypto_ec *e, const struct crypto_ec_point *p,
5449+ const struct crypto_bignum *b,
5450+ struct crypto_ec_point *res)
5451+{
5452+ if (TEST_FAIL())
5453+ return -1;
5454+
5455+ return mbedtls_ecp_mul(
5456+ (mbedtls_ecp_group *)e, (mbedtls_ecp_point *)res,
5457+ (const mbedtls_mpi *)b, (const mbedtls_ecp_point *)p,
5458+ mbedtls_ctr_drbg_random, crypto_mbedtls_ctr_drbg()) ? -1 : 0;
5459+}
5460+
5461+int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p)
5462+{
5463+ if (TEST_FAIL())
5464+ return -1;
5465+
5466+ if (mbedtls_ecp_get_type((mbedtls_ecp_group *)e)
5467+ == MBEDTLS_ECP_TYPE_MONTGOMERY) {
5468+ /* e.g. MBEDTLS_ECP_DP_CURVE25519 and MBEDTLS_ECP_DP_CURVE448 */
5469+ wpa_printf(MSG_ERROR,
5470+ "%s not implemented for Montgomery curves",__func__);
5471+ return -1;
5472+ }
5473+
5474+ /* mbedtls does not provide an mbedtls_ecp_point invert function */
5475+ /* below works for Short Weierstrass; incorrect for Montgomery curves */
5476+ mbedtls_mpi *py = &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Y);
5477+ return mbedtls_ecp_is_zero((mbedtls_ecp_point *)p) /*point at infinity*/
5478+ || mbedtls_mpi_cmp_int(py, 0) == 0 /*point is its own inverse*/
5479+ || mbedtls_mpi_sub_abs(py, CRYPTO_EC_P(e), py) == 0 ? 0 : -1;
5480+}
5481+
5482+#ifdef MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED
5483+static int
5484+crypto_ec_point_y_sqr_weierstrass(mbedtls_ecp_group *e, const mbedtls_mpi *x,
5485+ mbedtls_mpi *y2)
5486+{
5487+ /* MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS y^2 = x^3 + a x + b */
5488+
5489+ /* Short Weierstrass elliptic curve group w/o A set treated as A = -3 */
5490+ /* Attempt to match mbedtls/library/ecp.c:ecp_check_pubkey_sw() behavior
5491+ * and elsewhere in mbedtls/library/ecp.c where if A is not set, it is
5492+ * treated as if A = -3. */
5493+
5494+ #if 0
5495+ /* y^2 = x^3 + ax + b */
5496+ mbedtls_mpi *A = &e->A;
5497+ mbedtls_mpi t, A_neg3;
5498+ if (&e->A.p == NULL) {
5499+ mbedtls_mpi_init(&A_neg3);
5500+ if (mbedtls_mpi_lset(&A_neg3, -3) != 0) {
5501+ mbedtls_mpi_free(&A_neg3);
5502+ return -1;
5503+ }
5504+ A = &A_neg3;
5505+ }
5506+ mbedtls_mpi_init(&t);
5507+ int ret = /* x^3 */
5508+ mbedtls_mpi_lset(&t, 3)
5509+ || mbedtls_mpi_exp_mod(y2, x, &t, &e->P, NULL)
5510+ /* ax */
5511+ || mbedtls_mpi_mul_mpi(y2, y2, A)
5512+ || mbedtls_mpi_mod_mpi(&t, &t, &e->P)
5513+ /* ax + b */
5514+ || mbedtls_mpi_add_mpi(&t, &t, &e->B)
5515+ || mbedtls_mpi_mod_mpi(&t, &t, &e->P)
5516+ /* x^3 + ax + b */
5517+ || mbedtls_mpi_add_mpi(&t, &t, y2) /* ax + b + x^3 */
5518+ || mbedtls_mpi_mod_mpi(y2, &t, &e->P);
5519+ mbedtls_mpi_free(&t);
5520+ if (A == &A_neg3)
5521+ mbedtls_mpi_free(&A_neg3);
5522+ return ret; /* 0: success, non-zero: failure */
5523+ #else
5524+ /* y^2 = x^3 + ax + b = (x^2 + a)x + b */
5525+ return /* x^2 */
5526+ mbedtls_mpi_mul_mpi(y2, x, x)
5527+ || mbedtls_mpi_mod_mpi(y2, y2, &e->P)
5528+ /* x^2 + a */
5529+ || (e->A.MBEDTLS_PRIVATE(p)
5530+ ? mbedtls_mpi_add_mpi(y2, y2, &e->A)
5531+ : mbedtls_mpi_sub_int(y2, y2, 3))
5532+ || mbedtls_mpi_mod_mpi(y2, y2, &e->P)
5533+ /* (x^2 + a)x */
5534+ || mbedtls_mpi_mul_mpi(y2, y2, x)
5535+ || mbedtls_mpi_mod_mpi(y2, y2, &e->P)
5536+ /* (x^2 + a)x + b */
5537+ || mbedtls_mpi_add_mpi(y2, y2, &e->B)
5538+ || mbedtls_mpi_mod_mpi(y2, y2, &e->P);
5539+ #endif
5540+}
5541+#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */
5542+
5543+#if 0 /* not used by hostap */
5544+#ifdef MBEDTLS_ECP_MONTGOMERY_ENABLED
5545+static int
5546+crypto_ec_point_y_sqr_montgomery(mbedtls_ecp_group *e, const mbedtls_mpi *x,
5547+ mbedtls_mpi *y2)
5548+{
5549+ /* XXX: !!! must be reviewed and audited for correctness !!! */
5550+
5551+ /* MBEDTLS_ECP_TYPE_MONTGOMERY y^2 = x^3 + a x^2 + x */
5552+
5553+ /* y^2 = x^3 + a x^2 + x = (x + a)x^2 + x */
5554+ mbedtls_mpi x2;
5555+ mbedtls_mpi_init(&x2);
5556+ int ret = /* x^2 */
5557+ mbedtls_mpi_mul_mpi(&x2, x, x)
5558+ || mbedtls_mpi_mod_mpi(&x2, &x2, &e->P)
5559+ /* x + a */
5560+ || mbedtls_mpi_add_mpi(y2, x, &e->A)
5561+ || mbedtls_mpi_mod_mpi(y2, y2, &e->P)
5562+ /* (x + a)x^2 */
5563+ || mbedtls_mpi_mul_mpi(y2, y2, &x2)
5564+ || mbedtls_mpi_mod_mpi(y2, y2, &e->P)
5565+ /* (x + a)x^2 + x */
5566+ || mbedtls_mpi_add_mpi(y2, y2, x)
5567+ || mbedtls_mpi_mod_mpi(y2, y2, &e->P);
5568+ mbedtls_mpi_free(&x2);
5569+ return ret; /* 0: success, non-zero: failure */
5570+}
5571+#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */
5572+#endif
5573+
5574+struct crypto_bignum *
5575+crypto_ec_point_compute_y_sqr(struct crypto_ec *e,
5576+ const struct crypto_bignum *x)
5577+{
5578+ if (TEST_FAIL())
5579+ return NULL;
5580+
5581+ mbedtls_mpi *y2 = os_malloc(sizeof(*y2));
5582+ if (y2 == NULL)
5583+ return NULL;
5584+ mbedtls_mpi_init(y2);
5585+
5586+ #ifdef MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED
5587+ if (mbedtls_ecp_get_type((mbedtls_ecp_group *)e)
5588+ == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS
5589+ && crypto_ec_point_y_sqr_weierstrass((mbedtls_ecp_group *)e,
5590+ (const mbedtls_mpi *)x,
5591+ y2) == 0)
5592+ return (struct crypto_bignum *)y2;
5593+ #endif
5594+ #if 0 /* not used by hostap */
5595+ #ifdef MBEDTLS_ECP_MONTGOMERY_ENABLED
5596+ if (mbedtls_ecp_get_type((mbedtls_ecp_group *)e)
5597+ == MBEDTLS_ECP_TYPE_MONTGOMERY
5598+ && crypto_ec_point_y_sqr_montgomery((mbedtls_ecp_group *)e,
5599+ (const mbedtls_mpi *)x,
5600+ y2) == 0)
5601+ return (struct crypto_bignum *)y2;
5602+ #endif
5603+ #endif
5604+
5605+ mbedtls_mpi_free(y2);
5606+ os_free(y2);
5607+ return NULL;
5608+}
5609+
5610+int crypto_ec_point_is_at_infinity(struct crypto_ec *e,
5611+ const struct crypto_ec_point *p)
5612+{
5613+ return mbedtls_ecp_is_zero((mbedtls_ecp_point *)p);
5614+}
5615+
5616+int crypto_ec_point_is_on_curve(struct crypto_ec *e,
5617+ const struct crypto_ec_point *p)
5618+{
5619+ #if 1
5620+ return mbedtls_ecp_check_pubkey((const mbedtls_ecp_group *)e,
5621+ (const mbedtls_ecp_point *)p) == 0;
5622+ #else
5623+ /* compute y^2 mod P and compare to y^2 mod P */
5624+ /*(ref: src/eap_common/eap_pwd_common.c:compute_password_element())*/
5625+ const mbedtls_mpi *px = &((const mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(X);
5626+ mbedtls_mpi *cy2 = (mbedtls_mpi *)
5627+ crypto_ec_point_compute_y_sqr(e, (const struct crypto_bignum *)px);
5628+ if (cy2 == NULL)
5629+ return 0;
5630+
5631+ mbedtls_mpi y2;
5632+ mbedtls_mpi_init(&y2);
5633+ const mbedtls_mpi *py = &((const mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Y);
5634+ int is_on_curve = mbedtls_mpi_mul_mpi(&y2, py, py) /* y^2 mod P */
5635+ || mbedtls_mpi_mod_mpi(&y2, &y2, CRYPTO_EC_P(e))
5636+ || mbedtls_mpi_cmp_mpi(&y2, cy2) != 0 ? 0 : 1;
5637+
5638+ mbedtls_mpi_free(&y2);
5639+ mbedtls_mpi_free(cy2);
5640+ os_free(cy2);
5641+ return is_on_curve;
5642+ #endif
5643+}
5644+
5645+int crypto_ec_point_cmp(const struct crypto_ec *e,
5646+ const struct crypto_ec_point *a,
5647+ const struct crypto_ec_point *b)
5648+{
5649+ return mbedtls_ecp_point_cmp((const mbedtls_ecp_point *)a,
5650+ (const mbedtls_ecp_point *)b);
5651+}
5652+
5653+#if !defined(CONFIG_NO_STDOUT_DEBUG)
5654+void crypto_ec_point_debug_print(const struct crypto_ec *e,
5655+ const struct crypto_ec_point *p,
5656+ const char *title)
5657+{
5658+ u8 x[MBEDTLS_MPI_MAX_SIZE];
5659+ u8 y[MBEDTLS_MPI_MAX_SIZE];
5660+ size_t len = CRYPTO_EC_plen(e);
5661+ /* crypto_ec_point_to_bin ought to take (const struct crypto_ec *e) */
5662+ struct crypto_ec *ee;
5663+ *(const struct crypto_ec **)&ee = e; /*(cast away const)*/
5664+ if (crypto_ec_point_to_bin(ee, p, x, y) == 0) {
5665+ if (title)
5666+ wpa_printf(MSG_DEBUG, "%s", title);
5667+ wpa_hexdump(MSG_DEBUG, "x:", x, len);
5668+ wpa_hexdump(MSG_DEBUG, "y:", y, len);
5669+ }
5670+}
5671+#endif
5672+
5673+
5674+struct crypto_ec_key * crypto_ec_key_parse_priv(const u8 *der, size_t der_len)
5675+{
5676+ mbedtls_pk_context *ctx = os_malloc(sizeof(*ctx));
5677+ if (ctx == NULL)
5678+ return NULL;
5679+ mbedtls_pk_init(ctx);
5680+ #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */
5681+ if (mbedtls_pk_parse_key(ctx, der, der_len, NULL, 0) == 0)
5682+ #else
5683+ if (mbedtls_pk_parse_key(ctx, der, der_len, NULL, 0,
5684+ mbedtls_ctr_drbg_random,
5685+ crypto_mbedtls_ctr_drbg()) == 0)
5686+ #endif
5687+ return (struct crypto_ec_key *)ctx;
5688+
5689+ mbedtls_pk_free(ctx);
5690+ os_free(ctx);
5691+ return NULL;
5692+}
5693+
5694+#ifdef CRYPTO_MBEDTLS_CRYPTO_HPKE
5695+#ifdef CONFIG_MODULE_TESTS
5696+/*(for crypto_module_tests.c)*/
5697+struct crypto_ec_key * crypto_ec_key_set_priv(int group,
5698+ const u8 *raw, size_t raw_len)
5699+{
5700+ mbedtls_ecp_group_id grp_id =
5701+ crypto_mbedtls_ecp_group_id_from_ike_id(group);
5702+ if (grp_id == MBEDTLS_ECP_DP_NONE)
5703+ return NULL;
5704+ const mbedtls_pk_info_t *pk_info =
5705+ mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
5706+ if (pk_info == NULL)
5707+ return NULL;
5708+ mbedtls_pk_context *ctx = os_malloc(sizeof(*ctx));
5709+ if (ctx == NULL)
5710+ return NULL;
5711+ mbedtls_pk_init(ctx);
5712+ if (mbedtls_pk_setup(ctx, pk_info) == 0
5713+ && mbedtls_ecp_read_key(grp_id,mbedtls_pk_ec(*ctx),raw,raw_len) == 0) {
5714+ return (struct crypto_ec_key *)ctx;
5715+ }
5716+
5717+ mbedtls_pk_free(ctx);
5718+ os_free(ctx);
5719+ return NULL;
5720+}
5721+#endif
5722+#endif
5723+
5724+#include <mbedtls/error.h>
5725+#include <mbedtls/oid.h>
5726+static int crypto_mbedtls_pk_parse_subpubkey_compressed(mbedtls_pk_context *ctx, const u8 *der, size_t der_len)
5727+{
5728+ /* The following is modified from:
5729+ * mbedtls/library/pkparse.c:mbedtls_pk_parse_subpubkey()
5730+ * mbedtls/library/pkparse.c:pk_get_pk_alg()
5731+ * mbedtls/library/pkparse.c:pk_use_ecparams()
5732+ */
5733+ mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
5734+ const mbedtls_pk_info_t *pk_info;
5735+ int ret;
5736+ size_t len;
5737+ const unsigned char *end = der+der_len;
5738+ unsigned char *p;
5739+ *(const unsigned char **)&p = der;
5740+
5741+ if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
5742+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
5743+ {
5744+ return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
5745+ }
5746+
5747+ end = p + len;
5748+
5749+ /*
5750+ if( ( ret = pk_get_pk_alg( &p, end, &pk_alg, &alg_params ) ) != 0 )
5751+ return( ret );
5752+ */
5753+ mbedtls_asn1_buf alg_oid, params;
5754+ memset( &params, 0, sizeof(mbedtls_asn1_buf) );
5755+ if( ( ret = mbedtls_asn1_get_alg( &p, end, &alg_oid, &params ) ) != 0 )
5756+ return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_ALG, ret ) );
5757+ if( mbedtls_oid_get_pk_alg( &alg_oid, &pk_alg ) != 0 )
5758+ return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
5759+
5760+ if( ( ret = mbedtls_asn1_get_bitstring_null( &p, end, &len ) ) != 0 )
5761+ return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, ret ) );
5762+
5763+ if( p + len != end )
5764+ return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY,
5765+ MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
5766+
5767+ if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL )
5768+ return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
5769+
5770+ if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 )
5771+ return( ret );
5772+
5773+ /* assume mbedtls_pk_parse_subpubkey(&der, der+der_len, ctx)
5774+ * has already run with ctx initialized up to pk_get_ecpubkey(),
5775+ * and pk_get_ecpubkey() has returned MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
5776+ *
5777+ * mbedtls mbedtls_ecp_point_read_binary()
5778+ * does not handle point in COMPRESSED format
5779+ *
5780+ * (validate assumption that algorithm is EC) */
5781+ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*ctx);
5782+ if (ecp_kp == NULL)
5783+ return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
5784+ mbedtls_ecp_group *ecp_kp_grp = &ecp_kp->MBEDTLS_PRIVATE(grp);
5785+ mbedtls_ecp_point *ecp_kp_Q = &ecp_kp->MBEDTLS_PRIVATE(Q);
5786+ mbedtls_ecp_group_id grp_id;
5787+
5788+
5789+ /* mbedtls/library/pkparse.c:pk_use_ecparams() */
5790+
5791+ if( params.tag == MBEDTLS_ASN1_OID )
5792+ {
5793+ if( mbedtls_oid_get_ec_grp( &params, &grp_id ) != 0 )
5794+ return( MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE );
5795+ }
5796+ else
5797+ {
5798+#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED)
5799+ /*(large code block not copied from mbedtls; unsupported)*/
5800+ #if 0
5801+ if( ( ret = pk_group_id_from_specified( &params, &grp_id ) ) != 0 )
5802+ return( ret );
5803+ #endif
5804+#endif
5805+ return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
5806+ }
5807+
5808+ /*
5809+ * grp may already be initialized; if so, make sure IDs match
5810+ */
5811+ if( ecp_kp_grp->id != MBEDTLS_ECP_DP_NONE && ecp_kp_grp->id != grp_id )
5812+ return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
5813+
5814+ if( ( ret = mbedtls_ecp_group_load( ecp_kp_grp, grp_id ) ) != 0 )
5815+ return( ret );
5816+
5817+
5818+ /* (validate assumption that EC point is in COMPRESSED format) */
5819+ len = CRYPTO_EC_plen(ecp_kp_grp);
5820+ if( mbedtls_ecp_get_type(ecp_kp_grp) != MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS
5821+ || (end - p) != 1+len
5822+ || (*p != 0x02 && *p != 0x03) )
5823+ return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
5824+
5825+ /* Instead of calling mbedtls/library/pkparse.c:pk_get_ecpubkey() to call
5826+ * mbedtls_ecp_point_read_binary(), manually parse point into ecp_kp_Q */
5827+ mbedtls_mpi *X = &ecp_kp_Q->MBEDTLS_PRIVATE(X);
5828+ mbedtls_mpi *Y = &ecp_kp_Q->MBEDTLS_PRIVATE(Y);
5829+ mbedtls_mpi *Z = &ecp_kp_Q->MBEDTLS_PRIVATE(Z);
5830+ ret = mbedtls_mpi_lset(Z, 1);
5831+ if (ret != 0)
5832+ return( ret );
5833+ ret = mbedtls_mpi_read_binary(X, p+1, len);
5834+ if (ret != 0)
5835+ return( ret );
5836+ /* derive Y
5837+ * (similar derivation of Y in crypto_mbedtls.c:crypto_ecdh_set_peerkey())*/
5838+ ret = mbedtls_mpi_copy(Y, X) /*(Y is used as input and output obj below)*/
5839+ || crypto_mbedtls_short_weierstrass_derive_y(ecp_kp_grp, Y, (*p & 1));
5840+ if (ret != 0)
5841+ return( ret );
5842+
5843+ return mbedtls_ecp_check_pubkey( ecp_kp_grp, ecp_kp_Q );
5844+}
5845+
5846+struct crypto_ec_key * crypto_ec_key_parse_pub(const u8 *der, size_t der_len)
5847+{
5848+ mbedtls_pk_context *ctx = os_malloc(sizeof(*ctx));
5849+ if (ctx == NULL)
5850+ return NULL;
5851+ mbedtls_pk_init(ctx);
5852+ /*int rc = mbedtls_pk_parse_subpubkey(&der, der+der_len, ctx);*/
5853+ int rc = mbedtls_pk_parse_public_key(ctx, der, der_len);
5854+ if (rc == 0)
5855+ return (struct crypto_ec_key *)ctx;
5856+ else if (rc == MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) {
5857+ /* mbedtls mbedtls_ecp_point_read_binary()
5858+ * does not handle point in COMPRESSED format; parse internally */
5859+ rc = crypto_mbedtls_pk_parse_subpubkey_compressed(ctx,der,der_len);
5860+ if (rc == 0)
5861+ return (struct crypto_ec_key *)ctx;
5862+ }
5863+
5864+ mbedtls_pk_free(ctx);
5865+ os_free(ctx);
5866+ return NULL;
5867+}
5868+
5869+#ifdef CRYPTO_MBEDTLS_CRYPTO_EC_DPP
5870+
5871+static struct crypto_ec_key *
5872+crypto_ec_key_set_pub_point_for_group(mbedtls_ecp_group_id grp_id,
5873+ const mbedtls_ecp_point *pub,
5874+ const u8 *buf, size_t len)
5875+{
5876+ const mbedtls_pk_info_t *pk_info =
5877+ mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
5878+ if (pk_info == NULL)
5879+ return NULL;
5880+ mbedtls_pk_context *ctx = os_malloc(sizeof(*ctx));
5881+ if (ctx == NULL)
5882+ return NULL;
5883+ mbedtls_pk_init(ctx);
5884+ if (mbedtls_pk_setup(ctx, pk_info) == 0) {
5885+ /* (Is private key generation necessary for callers?)
5886+ * alt: gen key then overwrite Q
5887+ * mbedtls_ecp_gen_key(grp_id, ecp_kp,
5888+ * mbedtls_ctr_drbg_random,
5889+ * crypto_mbedtls_ctr_drbg()) == 0
5890+ */
5891+ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*ctx);
5892+ mbedtls_ecp_group *ecp_kp_grp = &ecp_kp->MBEDTLS_PRIVATE(grp);
5893+ mbedtls_ecp_point *ecp_kp_Q = &ecp_kp->MBEDTLS_PRIVATE(Q);
5894+ mbedtls_mpi *ecp_kp_d = &ecp_kp->MBEDTLS_PRIVATE(d);
5895+ if (mbedtls_ecp_group_load(ecp_kp_grp, grp_id) == 0
5896+ && (pub
5897+ ? mbedtls_ecp_copy(ecp_kp_Q, pub) == 0
5898+ : mbedtls_ecp_point_read_binary(ecp_kp_grp, ecp_kp_Q,
5899+ buf, len) == 0)
5900+ && mbedtls_ecp_gen_privkey(ecp_kp_grp, ecp_kp_d,
5901+ mbedtls_ctr_drbg_random,
5902+ crypto_mbedtls_ctr_drbg()) == 0){
5903+ return (struct crypto_ec_key *)ctx;
5904+ }
5905+ }
5906+
5907+ mbedtls_pk_free(ctx);
5908+ os_free(ctx);
5909+ return NULL;
5910+}
5911+
5912+struct crypto_ec_key * crypto_ec_key_set_pub(int group, const u8 *x,
5913+ const u8 *y, size_t len)
5914+{
5915+ mbedtls_ecp_group_id grp_id =
5916+ crypto_mbedtls_ecp_group_id_from_ike_id(group);
5917+ if (grp_id == MBEDTLS_ECP_DP_NONE)
5918+ return NULL;
5919+ if (len > MBEDTLS_MPI_MAX_SIZE)
5920+ return NULL;
5921+ u8 buf[1+MBEDTLS_MPI_MAX_SIZE*2];
5922+ buf[0] = 0x04; /* assume x,y for Short Weierstrass */
5923+ os_memcpy(buf+1, x, len);
5924+ os_memcpy(buf+1+len, y, len);
5925+
5926+ return crypto_ec_key_set_pub_point_for_group(grp_id,NULL,buf,1+len*2);
5927+}
5928+
5929+struct crypto_ec_key *
5930+crypto_ec_key_set_pub_point(struct crypto_ec *e,
5931+ const struct crypto_ec_point *pub)
5932+{
5933+ mbedtls_ecp_group_id grp_id = ((mbedtls_ecp_group *)e)->id;
5934+ mbedtls_ecp_point *p = (mbedtls_ecp_point *)pub;
5935+ return crypto_ec_key_set_pub_point_for_group(grp_id, p, NULL, 0);
5936+}
5937+
5938+
5939+struct crypto_ec_key * crypto_ec_key_gen(int group)
5940+{
5941+ mbedtls_pk_context *ctx = os_malloc(sizeof(*ctx));
5942+ if (ctx == NULL)
5943+ return NULL;
5944+ mbedtls_pk_init(ctx);
5945+ if (crypto_mbedtls_keypair_gen(group, ctx) == 0)
5946+ return (struct crypto_ec_key *)ctx;
5947+ mbedtls_pk_free(ctx);
5948+ os_free(ctx);
5949+ return NULL;
5950+}
5951+
5952+#endif /* CRYPTO_MBEDTLS_CRYPTO_EC_DPP */
5953+
5954+void crypto_ec_key_deinit(struct crypto_ec_key *key)
5955+{
5956+ mbedtls_pk_free((mbedtls_pk_context *)key);
5957+ os_free(key);
5958+}
5959+
5960+struct wpabuf * crypto_ec_key_get_subject_public_key(struct crypto_ec_key *key)
5961+{
5962+ /* (similar to crypto_ec_key_get_pubkey_point(),
5963+ * but compressed point format and ASN.1 DER wrapping)*/
5964+#ifndef MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES /*(mbedtls/library/pkwrite.h)*/
5965+#define MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES ( 30 + 2 * MBEDTLS_ECP_MAX_BYTES )
5966+#endif
5967+ unsigned char buf[MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES];
5968+ int len = mbedtls_pk_write_pubkey_der((mbedtls_pk_context *)key,
5969+ buf, sizeof(buf));
5970+ if (len < 0)
5971+ return NULL;
5972+ /* Note: data is written at the end of the buffer! Use the
5973+ * return value to determine where you should start
5974+ * using the buffer */
5975+ unsigned char *p = buf+sizeof(buf)-len;
5976+
5977+ #ifdef MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED
5978+ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key);
5979+ if (ecp_kp == NULL)
5980+ return NULL;
5981+ mbedtls_ecp_group *grp = &ecp_kp->MBEDTLS_PRIVATE(grp);
5982+ /* Note: sae_pk.c expects pubkey point in compressed format,
5983+ * but mbedtls_pk_write_pubkey_der() writes uncompressed format.
5984+ * Manually translate format and update lengths in DER format */
5985+ if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {
5986+ unsigned char *end = buf+sizeof(buf);
5987+ size_t n;
5988+ /* SubjectPublicKeyInfo SEQUENCE */
5989+ mbedtls_asn1_get_tag(&p, end, &n,
5990+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
5991+ /* algorithm AlgorithmIdentifier */
5992+ unsigned char *a = p;
5993+ size_t alen;
5994+ mbedtls_asn1_get_tag(&p, end, &alen,
5995+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
5996+ p += alen;
5997+ alen = (size_t)(p - a);
5998+ /* subjectPublicKey BIT STRING */
5999+ mbedtls_asn1_get_tag(&p, end, &n, MBEDTLS_ASN1_BIT_STRING);
6000+ /* rewrite into compressed point format and rebuild ASN.1 */
6001+ p[1] = (buf[sizeof(buf)-1] & 1) ? 0x03 : 0x02;
6002+ n = 1 + 1 + (n-2)/2;
6003+ len = mbedtls_asn1_write_len(&p, buf, n) + (int)n;
6004+ len += mbedtls_asn1_write_tag(&p, buf, MBEDTLS_ASN1_BIT_STRING);
6005+ os_memmove(p-alen, a, alen);
6006+ len += alen;
6007+ p -= alen;
6008+ len += mbedtls_asn1_write_len(&p, buf, (size_t)len);
6009+ len += mbedtls_asn1_write_tag(&p, buf,
6010+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
6011+ }
6012+ #endif
6013+ return wpabuf_alloc_copy(p, (size_t)len);
6014+}
6015+
6016+#ifdef CRYPTO_MBEDTLS_CRYPTO_EC_DPP
6017+
6018+struct wpabuf * crypto_ec_key_get_ecprivate_key(struct crypto_ec_key *key,
6019+ bool include_pub)
6020+{
6021+#ifndef MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES /*(mbedtls/library/pkwrite.h)*/
6022+#define MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES ( 29 + 3 * MBEDTLS_ECP_MAX_BYTES )
6023+#endif
6024+ unsigned char priv[MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES];
6025+ int privlen = mbedtls_pk_write_key_der((mbedtls_pk_context *)key,
6026+ priv, sizeof(priv));
6027+ if (privlen < 0)
6028+ return NULL;
6029+
6030+ struct wpabuf *wbuf;
6031+
6032+ /* Note: data is written at the end of the buffer! Use the
6033+ * return value to determine where you should start
6034+ * using the buffer */
6035+ /* mbedtls_pk_write_key_der() includes publicKey in DER */
6036+ if (include_pub)
6037+ wbuf = wpabuf_alloc_copy(priv+sizeof(priv)-privlen, privlen);
6038+ else {
6039+ /* calculate publicKey offset and skip from end of buffer */
6040+ unsigned char *p = priv+sizeof(priv)-privlen;
6041+ unsigned char *end = priv+sizeof(priv);
6042+ size_t len;
6043+ /* ECPrivateKey SEQUENCE */
6044+ mbedtls_asn1_get_tag(&p, end, &len,
6045+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
6046+ /* version INTEGER */
6047+ unsigned char *v = p;
6048+ mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER);
6049+ p += len;
6050+ /* privateKey OCTET STRING */
6051+ mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
6052+ p += len;
6053+ /* parameters ECParameters */
6054+ mbedtls_asn1_get_tag(&p, end, &len,
6055+ MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED);
6056+ p += len;
6057+
6058+ /* write new SEQUENCE header (we know that it fits in priv[]) */
6059+ len = (size_t)(p - v);
6060+ p = v;
6061+ len += mbedtls_asn1_write_len(&p, priv, len);
6062+ len += mbedtls_asn1_write_tag(&p, priv,
6063+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
6064+ wbuf = wpabuf_alloc_copy(p, len);
6065+ }
6066+
6067+ forced_memzero(priv, sizeof(priv));
6068+ return wbuf;
6069+}
6070+
6071+struct wpabuf * crypto_ec_key_get_pubkey_point(struct crypto_ec_key *key,
6072+ int prefix)
6073+{
6074+ /*(similarities to crypto_ecdh_get_pubkey(), but different struct)*/
6075+ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key);
6076+ if (ecp_kp == NULL)
6077+ return NULL;
6078+ mbedtls_ecp_group *grp = &ecp_kp->MBEDTLS_PRIVATE(grp);
6079+ size_t len = CRYPTO_EC_plen(grp);
6080+ #ifdef MBEDTLS_ECP_MONTGOMERY_ENABLED
6081+ /* len */
6082+ #endif
6083+ #ifdef MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED
6084+ if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS)
6085+ len = len*2+1;
6086+ #endif
6087+ struct wpabuf *buf = wpabuf_alloc(len);
6088+ if (buf == NULL)
6089+ return NULL;
6090+ mbedtls_ecp_point *ecp_kp_Q = &ecp_kp->MBEDTLS_PRIVATE(Q);
6091+ if (mbedtls_ecp_point_write_binary(grp, ecp_kp_Q,
6092+ MBEDTLS_ECP_PF_UNCOMPRESSED, &len,
6093+ wpabuf_mhead_u8(buf), len) == 0) {
6094+ if (!prefix) /* Remove 0x04 prefix if requested */
6095+ os_memmove(wpabuf_mhead(buf),wpabuf_mhead(buf)+1,--len);
6096+ wpabuf_put(buf, len);
6097+ return buf;
6098+ }
6099+
6100+ wpabuf_free(buf);
6101+ return NULL;
6102+}
6103+
6104+struct crypto_ec_point *
6105+crypto_ec_key_get_public_key(struct crypto_ec_key *key)
6106+{
6107+ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key);
6108+ if (ecp_kp == NULL)
6109+ return NULL;
6110+ mbedtls_ecp_point *p = os_malloc(sizeof(*p));
6111+ if (p != NULL) {
6112+ /*(mbedtls_ecp_export() uses &ecp_kp->MBEDTLS_PRIVATE(grp))*/
6113+ mbedtls_ecp_point_init(p);
6114+ mbedtls_ecp_point *ecp_kp_Q = &ecp_kp->MBEDTLS_PRIVATE(Q);
6115+ if (mbedtls_ecp_copy(p, ecp_kp_Q)) {
6116+ mbedtls_ecp_point_free(p);
6117+ os_free(p);
6118+ p = NULL;
6119+ }
6120+ }
6121+ return (struct crypto_ec_point *)p;
6122+}
6123+
6124+struct crypto_bignum *
6125+crypto_ec_key_get_private_key(struct crypto_ec_key *key)
6126+{
6127+ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key);
6128+ if (ecp_kp == NULL)
6129+ return NULL;
6130+ mbedtls_mpi *bn = os_malloc(sizeof(*bn));
6131+ if (bn) {
6132+ /*(mbedtls_ecp_export() uses &ecp_kp->MBEDTLS_PRIVATE(grp))*/
6133+ mbedtls_mpi_init(bn);
6134+ mbedtls_mpi *ecp_kp_d = &ecp_kp->MBEDTLS_PRIVATE(d);
6135+ if (mbedtls_mpi_copy(bn, ecp_kp_d)) {
6136+ mbedtls_mpi_free(bn);
6137+ os_free(bn);
6138+ bn = NULL;
6139+ }
6140+ }
6141+ return (struct crypto_bignum *)bn;
6142+}
6143+
6144+#endif /* CRYPTO_MBEDTLS_CRYPTO_EC_DPP */
6145+
6146+static mbedtls_md_type_t crypto_ec_key_sign_md(size_t len)
6147+{
6148+ /* get mbedtls_md_type_t from length of hash data to be signed */
6149+ switch (len) {
6150+ case 64: return MBEDTLS_MD_SHA512;
6151+ case 48: return MBEDTLS_MD_SHA384;
6152+ case 32: return MBEDTLS_MD_SHA256;
6153+ case 20: return MBEDTLS_MD_SHA1;
6154+ case 16: return MBEDTLS_MD_MD5;
6155+ default: return MBEDTLS_MD_NONE;
6156+ }
6157+}
6158+
6159+struct wpabuf * crypto_ec_key_sign(struct crypto_ec_key *key, const u8 *data,
6160+ size_t len)
6161+{
6162+ #ifndef MBEDTLS_PK_SIGNATURE_MAX_SIZE /*(defined since mbedtls 2.20.0)*/
6163+ #if MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_MPI_MAX_SIZE
6164+ #define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN
6165+ #else
6166+ #define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE
6167+ #endif
6168+ #endif
6169+ size_t sig_len = MBEDTLS_PK_SIGNATURE_MAX_SIZE;
6170+ struct wpabuf *buf = wpabuf_alloc(sig_len);
6171+ if (buf == NULL)
6172+ return NULL;
6173+ if (mbedtls_pk_sign((mbedtls_pk_context *)key,
6174+ crypto_ec_key_sign_md(len), data, len,
6175+ wpabuf_mhead_u8(buf),
6176+ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
6177+ sig_len,
6178+ #endif
6179+ &sig_len,
6180+ mbedtls_ctr_drbg_random,
6181+ crypto_mbedtls_ctr_drbg()) == 0) {
6182+ wpabuf_put(buf, sig_len);
6183+ return buf;
6184+ }
6185+
6186+ wpabuf_free(buf);
6187+ return NULL;
6188+}
6189+
6190+#ifdef CRYPTO_MBEDTLS_CRYPTO_EC_DPP
6191+struct wpabuf * crypto_ec_key_sign_r_s(struct crypto_ec_key *key,
6192+ const u8 *data, size_t len)
6193+{
6194+ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key);
6195+ if (ecp_kp == NULL)
6196+ return NULL;
6197+
6198+ size_t sig_len = MBEDTLS_ECDSA_MAX_LEN;
6199+ u8 buf[MBEDTLS_ECDSA_MAX_LEN];
6200+ if (mbedtls_ecdsa_write_signature(ecp_kp, crypto_ec_key_sign_md(len),
6201+ data, len, buf,
6202+ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
6203+ sig_len,
6204+ #endif
6205+ &sig_len,
6206+ mbedtls_ctr_drbg_random,
6207+ crypto_mbedtls_ctr_drbg())) {
6208+ return NULL;
6209+ }
6210+
6211+ /*(mbedtls_ecdsa_write_signature() writes signature in ASN.1)*/
6212+ /* parse ASN.1 to get r and s and lengths */
6213+ u8 *p = buf, *r, *s;
6214+ u8 *end = p + sig_len;
6215+ size_t rlen, slen;
6216+ mbedtls_asn1_get_tag(&p, end, &rlen,
6217+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
6218+ mbedtls_asn1_get_tag(&p, end, &rlen, MBEDTLS_ASN1_INTEGER);
6219+ r = p;
6220+ p += rlen;
6221+ mbedtls_asn1_get_tag(&p, end, &slen, MBEDTLS_ASN1_INTEGER);
6222+ s = p;
6223+
6224+ /* write raw r and s into out
6225+ * (including removal of leading 0 if added for ASN.1 integer)
6226+ * note: DPP caller expects raw r, s each padded to prime len */
6227+ mbedtls_ecp_group *ecp_kp_grp = &ecp_kp->MBEDTLS_PRIVATE(grp);
6228+ size_t plen = CRYPTO_EC_plen(ecp_kp_grp);
6229+ if (rlen > plen) {
6230+ r += (rlen - plen);
6231+ rlen = plen;
6232+ }
6233+ if (slen > plen) {
6234+ s += (slen - plen);
6235+ slen = plen;
6236+ }
6237+ struct wpabuf *out = wpabuf_alloc(plen*2);
6238+ if (out) {
6239+ wpabuf_put(out, plen*2);
6240+ p = wpabuf_mhead_u8(out);
6241+ os_memset(p, 0, plen*2);
6242+ os_memcpy(p+plen*1-rlen, r, rlen);
6243+ os_memcpy(p+plen*2-slen, s, slen);
6244+ }
6245+ return out;
6246+}
6247+#endif /* CRYPTO_MBEDTLS_CRYPTO_EC_DPP */
6248+
6249+int crypto_ec_key_verify_signature(struct crypto_ec_key *key, const u8 *data,
6250+ size_t len, const u8 *sig, size_t sig_len)
6251+{
6252+ switch (mbedtls_pk_verify((mbedtls_pk_context *)key,
6253+ crypto_ec_key_sign_md(len), data, len,
6254+ sig, sig_len)) {
6255+ case 0:
6256+ /*case MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH:*//* XXX: allow? */
6257+ return 1;
6258+ case MBEDTLS_ERR_ECP_VERIFY_FAILED:
6259+ return 0;
6260+ default:
6261+ return -1;
6262+ }
6263+}
6264+
6265+#ifdef CRYPTO_MBEDTLS_CRYPTO_EC_DPP
6266+int crypto_ec_key_verify_signature_r_s(struct crypto_ec_key *key,
6267+ const u8 *data, size_t len,
6268+ const u8 *r, size_t r_len,
6269+ const u8 *s, size_t s_len)
6270+{
6271+ /* reimplement mbedtls_ecdsa_read_signature() without encoding r and s
6272+ * into ASN.1 just for mbedtls_ecdsa_read_signature() to decode ASN.1 */
6273+ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key);
6274+ if (ecp_kp == NULL)
6275+ return -1;
6276+ mbedtls_ecp_group *ecp_kp_grp = &ecp_kp->MBEDTLS_PRIVATE(grp);
6277+ mbedtls_ecp_point *ecp_kp_Q = &ecp_kp->MBEDTLS_PRIVATE(Q);
6278+
6279+ mbedtls_mpi mpi_r;
6280+ mbedtls_mpi mpi_s;
6281+ mbedtls_mpi_init(&mpi_r);
6282+ mbedtls_mpi_init(&mpi_s);
6283+ int ret = mbedtls_mpi_read_binary(&mpi_r, r, r_len)
6284+ || mbedtls_mpi_read_binary(&mpi_s, s, s_len) ? -1 : 0;
6285+ if (ret == 0) {
6286+ ret = mbedtls_ecdsa_verify(ecp_kp_grp, data, len,
6287+ ecp_kp_Q, &mpi_r, &mpi_s);
6288+ ret = ret ? ret == MBEDTLS_ERR_ECP_BAD_INPUT_DATA ? 0 : -1 : 1;
6289+ }
6290+ mbedtls_mpi_free(&mpi_r);
6291+ mbedtls_mpi_free(&mpi_s);
6292+ return ret;
6293+}
6294+#endif /* CRYPTO_MBEDTLS_CRYPTO_EC_DPP */
6295+
6296+int crypto_ec_key_group(struct crypto_ec_key *key)
6297+{
6298+ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key);
6299+ if (ecp_kp == NULL)
6300+ return -1;
6301+ mbedtls_ecp_group *ecp_group = &ecp_kp->MBEDTLS_PRIVATE(grp);
6302+ return crypto_mbedtls_ike_id_from_ecp_group_id(ecp_group->id);
6303+}
6304+
6305+#ifdef CRYPTO_MBEDTLS_CRYPTO_EC_DPP
6306+
6307+int crypto_ec_key_cmp(struct crypto_ec_key *key1, struct crypto_ec_key *key2)
6308+{
6309+#if 0 /*(DPP is passing two public keys; unable to use pk_check_pair())*/
6310+ #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */
6311+ return mbedtls_pk_check_pair((const mbedtls_pk_context *)key1,
6312+ (const mbedtls_pk_context *)key2) ? -1 : 0;
6313+ #else
6314+ return mbedtls_pk_check_pair((const mbedtls_pk_context *)key1,
6315+ (const mbedtls_pk_context *)key2,
6316+ mbedtls_ctr_drbg_random,
6317+ crypto_mbedtls_ctr_drbg()) ? -1 : 0;
6318+ #endif
6319+#else
6320+ mbedtls_ecp_keypair *ecp_kp1=mbedtls_pk_ec(*(mbedtls_pk_context *)key1);
6321+ mbedtls_ecp_keypair *ecp_kp2=mbedtls_pk_ec(*(mbedtls_pk_context *)key2);
6322+ if (ecp_kp1 == NULL || ecp_kp2 == NULL)
6323+ return -1;
6324+ mbedtls_ecp_group *ecp_kp1_grp = &ecp_kp1->MBEDTLS_PRIVATE(grp);
6325+ mbedtls_ecp_group *ecp_kp2_grp = &ecp_kp2->MBEDTLS_PRIVATE(grp);
6326+ mbedtls_ecp_point *ecp_kp1_Q = &ecp_kp1->MBEDTLS_PRIVATE(Q);
6327+ mbedtls_ecp_point *ecp_kp2_Q = &ecp_kp2->MBEDTLS_PRIVATE(Q);
6328+ return ecp_kp1_grp->id != ecp_kp2_grp->id
6329+ || mbedtls_ecp_point_cmp(ecp_kp1_Q, ecp_kp2_Q) ? -1 : 0;
6330+#endif
6331+}
6332+
6333+void crypto_ec_key_debug_print(const struct crypto_ec_key *key,
6334+ const char *title)
6335+{
6336+ /* TBD: what info is desirable here and in what human readable format?*/
6337+ /*(crypto_openssl.c prints a human-readably public key and attributes)*/
6338+ #if 0
6339+ struct mbedtls_pk_debug_item debug_item;
6340+ if (mbedtls_pk_debug((const mbedtls_pk_context *)key, &debug_item))
6341+ return;
6342+ /* ... */
6343+ #endif
6344+ wpa_printf(MSG_DEBUG, "%s: %s not implemented", title, __func__);
6345+}
6346+
6347+#endif /* CRYPTO_MBEDTLS_CRYPTO_EC_DPP */
6348+
6349+#endif /* CRYPTO_MBEDTLS_CRYPTO_EC */
6350+
6351+
6352+#ifdef CRYPTO_MBEDTLS_CRYPTO_CSR
6353+
6354+#include <mbedtls/x509_csr.h>
6355+#include <mbedtls/oid.h>
6356+
6357+struct crypto_csr * crypto_csr_init(void)
6358+{
6359+ mbedtls_x509write_csr *csr = os_malloc(sizeof(*csr));
6360+ if (csr != NULL)
6361+ mbedtls_x509write_csr_init(csr);
6362+ return (struct crypto_csr *)csr;
6363+}
6364+
6365+struct crypto_csr * crypto_csr_verify(const struct wpabuf *req)
6366+{
6367+ /* future: look for alternatives to MBEDTLS_PRIVATE() access */
6368+
6369+ /* sole caller src/common/dpp_crypto.c:dpp_validate_csr()
6370+ * uses (mbedtls_x509_csr *) to obtain CSR_ATTR_CHALLENGE_PASSWORD
6371+ * so allocate different object (mbedtls_x509_csr *) and special-case
6372+ * object when used in crypto_csr_get_attribute() and when free()d in
6373+ * crypto_csr_deinit(). */
6374+
6375+ mbedtls_x509_csr *csr = os_malloc(sizeof(*csr));
6376+ if (csr == NULL)
6377+ return NULL;
6378+ mbedtls_x509_csr_init(csr);
6379+ const mbedtls_md_info_t *md_info;
6380+ unsigned char digest[MBEDTLS_MD_MAX_SIZE];
6381+ if (mbedtls_x509_csr_parse_der(csr,wpabuf_head(req),wpabuf_len(req))==0
6382+ && (md_info=mbedtls_md_info_from_type(csr->MBEDTLS_PRIVATE(sig_md)))
6383+ != NULL
6384+ && mbedtls_md(md_info, csr->cri.p, csr->cri.len, digest) == 0) {
6385+ switch (mbedtls_pk_verify(&csr->pk,csr->MBEDTLS_PRIVATE(sig_md),
6386+ digest, mbedtls_md_get_size(md_info),
6387+ csr->MBEDTLS_PRIVATE(sig).p,
6388+ csr->MBEDTLS_PRIVATE(sig).len)) {
6389+ case 0:
6390+ /*case MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH:*//* XXX: allow? */
6391+ return (struct crypto_csr *)((uintptr_t)csr | 1uL);
6392+ default:
6393+ break;
6394+ }
6395+ }
6396+
6397+ mbedtls_x509_csr_free(csr);
6398+ os_free(csr);
6399+ return NULL;
6400+}
6401+
6402+void crypto_csr_deinit(struct crypto_csr *csr)
6403+{
6404+ if ((uintptr_t)csr & 1uL) {
6405+ csr = (struct crypto_csr *)((uintptr_t)csr & ~1uL);
6406+ mbedtls_x509_csr_free((mbedtls_x509_csr *)csr);
6407+ }
6408+ else
6409+ mbedtls_x509write_csr_free((mbedtls_x509write_csr *)csr);
6410+ os_free(csr);
6411+}
6412+
6413+int crypto_csr_set_ec_public_key(struct crypto_csr *csr,
6414+ struct crypto_ec_key *key)
6415+{
6416+ mbedtls_x509write_csr_set_key((mbedtls_x509write_csr *)csr,
6417+ (mbedtls_pk_context *)key);
6418+ return 0;
6419+}
6420+
6421+int crypto_csr_set_name(struct crypto_csr *csr, enum crypto_csr_name type,
6422+ const char *name)
6423+{
6424+ /* specialized for src/common/dpp_crypto.c */
6425+
6426+ /* sole caller src/common/dpp_crypto.c:dpp_build_csr()
6427+ * calls this function only once, using type == CSR_NAME_CN
6428+ * (If called more than once, this code would need to append
6429+ * components to the subject name, which we could do by
6430+ * appending to (mbedtls_x509write_csr *) private member
6431+ * mbedtls_asn1_named_data *MBEDTLS_PRIVATE(subject)) */
6432+
6433+ const char *label;
6434+ switch (type) {
6435+ case CSR_NAME_CN: label = "CN="; break;
6436+ case CSR_NAME_SN: label = "SN="; break;
6437+ case CSR_NAME_C: label = "C="; break;
6438+ case CSR_NAME_O: label = "O="; break;
6439+ case CSR_NAME_OU: label = "OU="; break;
6440+ default: return -1;
6441+ }
6442+
6443+ size_t len = strlen(name);
6444+ struct wpabuf *buf = wpabuf_alloc(3+len+1);
6445+ if (buf == NULL)
6446+ return -1;
6447+ wpabuf_put_data(buf, label, strlen(label));
6448+ wpabuf_put_data(buf, name, len+1); /*(include trailing '\0')*/
6449+ /* Note: 'name' provided is set as given and should be backslash-escaped
6450+ * by caller when necessary, e.g. literal ',' which are not separating
6451+ * components should be backslash-escaped */
6452+
6453+ int ret =
6454+ mbedtls_x509write_csr_set_subject_name((mbedtls_x509write_csr *)csr,
6455+ wpabuf_head(buf)) ? -1 : 0;
6456+ wpabuf_free(buf);
6457+ return ret;
6458+}
6459+
6460+/* OBJ_pkcs9_challengePassword 1 2 840 113549 1 9 7 */
6461+static const char OBJ_pkcs9_challengePassword[] = MBEDTLS_OID_PKCS9 "\x07";
6462+
6463+int crypto_csr_set_attribute(struct crypto_csr *csr, enum crypto_csr_attr attr,
6464+ int attr_type, const u8 *value, size_t len)
6465+{
6466+ /* specialized for src/common/dpp_crypto.c */
6467+ /* sole caller src/common/dpp_crypto.c:dpp_build_csr() passes
6468+ * attr == CSR_ATTR_CHALLENGE_PASSWORD
6469+ * attr_type == ASN1_TAG_UTF8STRING */
6470+
6471+ const char *oid;
6472+ size_t oid_len;
6473+ switch (attr) {
6474+ case CSR_ATTR_CHALLENGE_PASSWORD:
6475+ oid = OBJ_pkcs9_challengePassword;
6476+ oid_len = sizeof(OBJ_pkcs9_challengePassword)-1;
6477+ break;
6478+ default:
6479+ return -1;
6480+ }
6481+
6482+ #if 0 /*(incorrect; sets an extension, not an attribute)*/
6483+ return mbedtls_x509write_csr_set_extension((mbedtls_x509write_csr *)csr,
6484+ oid, oid_len,
6485+ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
6486+ 0, /*(critical flag)*/
6487+ #endif
6488+ value, len) ? -1 : 0;
6489+ #else
6490+ (void)oid;
6491+ (void)oid_len;
6492+ #endif
6493+
6494+ /* mbedtls does not currently provide way to set an attribute in a CSR:
6495+ * https://github.com/Mbed-TLS/mbedtls/issues/4886 */
6496+ wpa_printf(MSG_ERROR,
6497+ "mbedtls does not currently support setting challengePassword "
6498+ "attribute in CSR");
6499+ return -1;
6500+}
6501+
6502+const u8 * mbedtls_x509_csr_attr_oid_value(mbedtls_x509_csr *csr,
6503+ const char *oid, size_t oid_len,
6504+ size_t *vlen, int *vtype)
6505+{
6506+ /* Note: mbedtls_x509_csr_parse_der() has parsed and validated CSR,
6507+ * so validation checks are not repeated here
6508+ *
6509+ * It would be nicer if (mbedtls_x509_csr *) had an mbedtls_x509_buf of
6510+ * Attributes (or at least a pointer) since mbedtls_x509_csr_parse_der()
6511+ * already parsed the rest of CertificationRequestInfo, some of which is
6512+ * repeated here to step to Attributes. Since csr->subject_raw.p points
6513+ * into csr->cri.p, which points into csr->raw.p, step over version and
6514+ * subject of CertificationRequestInfo (SEQUENCE) */
6515+ unsigned char *p = csr->subject_raw.p + csr->subject_raw.len;
6516+ unsigned char *end = csr->cri.p + csr->cri.len, *ext;
6517+ size_t len;
6518+
6519+ /* step over SubjectPublicKeyInfo */
6520+ mbedtls_asn1_get_tag(&p, end, &len,
6521+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
6522+ p += len;
6523+
6524+ /* Attributes
6525+ * { ATTRIBUTE:IOSet } ::= SET OF { SEQUENCE { OID, value } }
6526+ */
6527+ if (mbedtls_asn1_get_tag(&p, end, &len,
6528+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) != 0) {
6529+ return NULL;
6530+ }
6531+ while (p < end) {
6532+ if (mbedtls_asn1_get_tag(&p, end, &len,
6533+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
6534+ return NULL;
6535+ }
6536+ ext = p;
6537+ p += len;
6538+
6539+ if (mbedtls_asn1_get_tag(&ext,end,&len,MBEDTLS_ASN1_OID) != 0)
6540+ return NULL;
6541+ if (oid_len != len || 0 != memcmp(ext, oid, oid_len))
6542+ continue;
6543+
6544+ /* found oid; return value */
6545+ *vtype = *ext++; /* tag */
6546+ return (mbedtls_asn1_get_len(&ext,end,vlen) == 0) ? ext : NULL;
6547+ }
6548+
6549+ return NULL;
6550+}
6551+
6552+const u8 * crypto_csr_get_attribute(struct crypto_csr *csr,
6553+ enum crypto_csr_attr attr,
6554+ size_t *len, int *type)
6555+{
6556+ /* specialized for src/common/dpp_crypto.c */
6557+ /* sole caller src/common/dpp_crypto.c:dpp_build_csr() passes
6558+ * attr == CSR_ATTR_CHALLENGE_PASSWORD */
6559+
6560+ const char *oid;
6561+ size_t oid_len;
6562+ switch (attr) {
6563+ case CSR_ATTR_CHALLENGE_PASSWORD:
6564+ oid = OBJ_pkcs9_challengePassword;
6565+ oid_len = sizeof(OBJ_pkcs9_challengePassword)-1;
6566+ break;
6567+ default:
6568+ return NULL;
6569+ }
6570+
6571+ /* see crypto_csr_verify(); expecting (mbedtls_x509_csr *) tagged |=1 */
6572+ if (!((uintptr_t)csr & 1uL))
6573+ return NULL;
6574+ csr = (struct crypto_csr *)((uintptr_t)csr & ~1uL);
6575+
6576+ return mbedtls_x509_csr_attr_oid_value((mbedtls_x509_csr *)csr,
6577+ oid, oid_len, len, type);
6578+}
6579+
6580+struct wpabuf * crypto_csr_sign(struct crypto_csr *csr,
6581+ struct crypto_ec_key *key,
6582+ enum crypto_hash_alg algo)
6583+{
6584+ mbedtls_md_type_t sig_md;
6585+ switch (algo) {
6586+ #ifdef MBEDTLS_SHA256_C
6587+ case CRYPTO_HASH_ALG_SHA256: sig_md = MBEDTLS_MD_SHA256; break;
6588+ #endif
6589+ #ifdef MBEDTLS_SHA512_C
6590+ case CRYPTO_HASH_ALG_SHA384: sig_md = MBEDTLS_MD_SHA384; break;
6591+ case CRYPTO_HASH_ALG_SHA512: sig_md = MBEDTLS_MD_SHA512; break;
6592+ #endif
6593+ default:
6594+ return NULL;
6595+ }
6596+ mbedtls_x509write_csr_set_md_alg((mbedtls_x509write_csr *)csr, sig_md);
6597+
6598+ #if 0
6599+ unsigned char key_usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE
6600+ | MBEDTLS_X509_KU_KEY_CERT_SIGN;
6601+ if (mbedtls_x509write_csr_set_key_usage((mbedtls_x509write_csr *)csr,
6602+ key_usage))
6603+ return NULL;
6604+ #endif
6605+
6606+ #if 0
6607+ unsigned char ns_cert_type = MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT
6608+ | MBEDTLS_X509_NS_CERT_TYPE_EMAIL;
6609+ if (mbedtls_x509write_csr_set_ns_cert_type((mbedtls_x509write_csr *)csr,
6610+ ns_cert_type))
6611+ return NULL;
6612+ #endif
6613+
6614+ #if 0
6615+ /* mbedtls does not currently provide way to set an attribute in a CSR:
6616+ * https://github.com/Mbed-TLS/mbedtls/issues/4886
6617+ * XXX: hwsim dpp_enterprise test fails due to this limitation.
6618+ *
6619+ * Current usage of this function is solely by dpp_build_csr(),
6620+ * so as a kludge, might consider custom (struct crypto_csr *)
6621+ * containing (mbedtls_x509write_csr *) and a list of attributes
6622+ * (i.e. challengePassword). Might have to totally reimplement
6623+ * mbedtls_x509write_csr_der(); underlying x509write_csr_der_internal()
6624+ * handles signing the CSR. (This is more work that appending an
6625+ * Attributes section to end of CSR and adjusting ASN.1 length of CSR.)
6626+ */
6627+ #endif
6628+
6629+ unsigned char buf[4096]; /* XXX: large enough? too large? */
6630+ int len = mbedtls_x509write_csr_der((mbedtls_x509write_csr *)csr,
6631+ buf, sizeof(buf),
6632+ mbedtls_ctr_drbg_random,
6633+ crypto_mbedtls_ctr_drbg());
6634+ if (len < 0)
6635+ return NULL;
6636+ /* Note: data is written at the end of the buffer! Use the
6637+ * return value to determine where you should start
6638+ * using the buffer */
6639+ return wpabuf_alloc_copy(buf+sizeof(buf)-len, (size_t)len);
6640+}
6641+
6642+#endif /* CRYPTO_MBEDTLS_CRYPTO_CSR */
6643+
6644+
6645+#ifdef CRYPTO_MBEDTLS_CRYPTO_PKCS7
6646+
6647+#if 0
6648+#include <mbedtls/pkcs7.h> /* PKCS7 is not currently supported in mbedtls */
6649+#include <mbedtls/pem.h>
6650+#endif
6651+
6652+struct wpabuf * crypto_pkcs7_get_certificates(const struct wpabuf *pkcs7)
6653+{
6654+ /* PKCS7 is not currently supported in mbedtls */
6655+ return NULL;
6656+
6657+#if 0
6658+ /* https://github.com/naynajain/mbedtls-1 branch: development-pkcs7
6659+ * (??? potential future contribution to mbedtls ???) */
6660+
6661+ /* Note: PKCS7 signature *is not* verified by this function.
6662+ * The function interface does not provide for passing a certificate */
6663+
6664+ mbedtls_pkcs7 mpkcs7;
6665+ mbedtls_pkcs7_init(&mpkcs7);
6666+ int pkcs7_type = mbedtls_pkcs7_parse_der(wpabuf_head(pkcs7),
6667+ wpabuf_len(pkcs7),
6668+ &mpkcs7);
6669+ wpabuf *buf = NULL;
6670+ do {
6671+ if (pkcs7_type < 0)
6672+ break;
6673+
6674+ /* src/common/dpp.c:dpp_parse_cred_dot1x() interested in certs
6675+ * for wpa_supplicant/dpp_supplicant.c:wpas_dpp_add_network()
6676+ * (? are adding certificate headers and footers desired ?) */
6677+
6678+ /* development-pkcs7 branch does not currently provide
6679+ * additional interfaces to retrieve the parsed data */
6680+
6681+ mbedtls_x509_crt *certs =
6682+ &mpkcs7.MBEDTLS_PRIVATE(signed_data).MBEDTLS_PRIVATE(certs);
6683+ int ncerts =
6684+ mpkcs7.MBEDTLS_PRIVATE(signed_data).MBEDTLS_PRIVATE(no_of_certs);
6685+
6686+ /* allocate buffer for PEM (base64-encoded DER)
6687+ * plus header, footer, newlines, and some extra */
6688+ buf = wpabuf_alloc((wpabuf_len(pkcs7)+2)/3*4 + ncerts*64);
6689+ if (buf == NULL)
6690+ break;
6691+
6692+ #define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n"
6693+ #define PEM_END_CRT "-----END CERTIFICATE-----\n"
6694+ size_t olen;
6695+ for (int i = 0; i < ncerts; ++i) {
6696+ int ret = mbedtls_pem_write_buffer(
6697+ PEM_BEGIN_CRT, PEM_END_CRT,
6698+ certs[i].raw.p, certs[i].raw.len,
6699+ wpabuf_mhead(buf, 0), wpabuf_tailroom(buf),
6700+ &olen));
6701+ if (ret == 0)
6702+ wpabuf_put(buf, olen);
6703+ } else {
6704+ if (ret == MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL)
6705+ ret = wpabuf_resize(
6706+ &buf,olen-wpabuf_tailroom(buf));
6707+ if (ret == 0) {
6708+ --i;/*(adjust loop iterator for retry)*/
6709+ continue;
6710+ }
6711+ wpabuf_free(buf);
6712+ buf = NULL;
6713+ break;
6714+ }
6715+ }
6716+ } while (0);
6717+
6718+ mbedtls_pkcs7_free(&mpkcs7);
6719+ return buf;
6720+#endif
6721+}
6722+
6723+#endif /* CRYPTO_MBEDTLS_CRYPTO_PKCS7 */
6724+
6725+
6726+#ifdef MBEDTLS_ARC4_C
6727+#include <mbedtls/arc4.h>
6728+int rc4_skip(const u8 *key, size_t keylen, size_t skip,
6729+ u8 *data, size_t data_len)
6730+{
6731+ mbedtls_arc4_context ctx;
6732+ mbedtls_arc4_init(&ctx);
6733+ mbedtls_arc4_setup(&ctx, key, keylen);
6734+
6735+ if (skip) {
6736+ /*(prefer [16] on ancient hardware with smaller cache lines)*/
6737+ unsigned char skip_buf[64]; /*('skip' is generally small)*/
6738+ /*os_memset(skip_buf, 0, sizeof(skip_buf));*/ /*(necessary?)*/
6739+ size_t len;
6740+ do {
6741+ len = skip > sizeof(skip_buf) ? sizeof(skip_buf) : skip;
6742+ mbedtls_arc4_crypt(&ctx, len, skip_buf, skip_buf);
6743+ } while ((skip -= len));
6744+ }
6745+
6746+ int ret = mbedtls_arc4_crypt(&ctx, data_len, data, data);
6747+ mbedtls_arc4_free(&ctx);
6748+ return ret;
6749+}
6750+#endif
6751+
6752+
6753+/* duplicated in tls_mbedtls.c:tls_mbedtls_readfile()*/
6754+__attribute_noinline__
6755+static int crypto_mbedtls_readfile(const char *path, u8 **buf, size_t *n)
6756+{
6757+ #if 0 /* #ifdef MBEDTLS_FS_IO */
6758+ /*(includes +1 for '\0' needed by mbedtls PEM parsing funcs)*/
6759+ if (mbedtls_pk_load_file(path, (unsigned char **)buf, n) != 0) {
6760+ wpa_printf(MSG_ERROR, "error: mbedtls_pk_load_file %s", path);
6761+ return -1;
6762+ }
6763+ #else
6764+ /*(use os_readfile() so that we can use os_free()
6765+ *(if we use mbedtls_pk_load_file() above, macros prevent calling free()
6766+ * directly #if defined(OS_REJECT_C_LIB_FUNCTIONS) and calling os_free()
6767+ * on buf aborts in tests if buf not allocated via os_malloc())*/
6768+ *buf = (u8 *)os_readfile(path, n);
6769+ if (!*buf) {
6770+ wpa_printf(MSG_ERROR, "error: os_readfile %s", path);
6771+ return -1;
6772+ }
6773+ u8 *buf0 = os_realloc(*buf, *n+1);
6774+ if (!buf0) {
6775+ bin_clear_free(*buf, *n);
6776+ *buf = NULL;
6777+ return -1;
6778+ }
6779+ buf0[(*n)++] = '\0';
6780+ *buf = buf0;
6781+ #endif
6782+ return 0;
6783+}
6784+
6785+
6786+#ifdef CRYPTO_MBEDTLS_CRYPTO_RSA
6787+#ifdef MBEDTLS_RSA_C
6788+
6789+#include <mbedtls/pk.h>
6790+#include <mbedtls/rsa.h>
6791+
6792+struct crypto_rsa_key * crypto_rsa_key_read(const char *file, bool private_key)
6793+{
6794+ /* mbedtls_pk_parse_keyfile() and mbedtls_pk_parse_public_keyfile()
6795+ * require #ifdef MBEDTLS_FS_IO in mbedtls library. Prefer to use
6796+ * crypto_mbedtls_readfile(), which wraps os_readfile() */
6797+ u8 *data;
6798+ size_t len;
6799+ if (crypto_mbedtls_readfile(file, &data, &len) != 0)
6800+ return NULL;
6801+
6802+ mbedtls_pk_context *ctx = os_malloc(sizeof(*ctx));
6803+ if (ctx == NULL) {
6804+ bin_clear_free(data, len);
6805+ return NULL;
6806+ }
6807+ mbedtls_pk_init(ctx);
6808+
6809+ int rc;
6810+ rc = (private_key
6811+ ? mbedtls_pk_parse_key(ctx, data, len, NULL, 0
6812+ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
6813+ ,mbedtls_ctr_drbg_random,
6814+ crypto_mbedtls_ctr_drbg()
6815+ #endif
6816+ )
6817+ : mbedtls_pk_parse_public_key(ctx, data, len)) == 0
6818+ && mbedtls_pk_can_do(ctx, MBEDTLS_PK_RSA);
6819+
6820+ bin_clear_free(data, len);
6821+
6822+ if (rc) {
6823+ /* use MBEDTLS_RSA_PKCS_V21 padding for RSAES-OAEP */
6824+ /* use MBEDTLS_MD_SHA256 for these hostap interfaces */
6825+ #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */
6826+ /*(no return value in mbedtls 2.x)*/
6827+ mbedtls_rsa_set_padding(mbedtls_pk_rsa(*ctx),
6828+ MBEDTLS_RSA_PKCS_V21,
6829+ MBEDTLS_MD_SHA256);
6830+ #else
6831+ if (mbedtls_rsa_set_padding(mbedtls_pk_rsa(*ctx),
6832+ MBEDTLS_RSA_PKCS_V21,
6833+ MBEDTLS_MD_SHA256) == 0)
6834+ #endif
6835+ return (struct crypto_rsa_key *)ctx;
6836+ }
6837+
6838+ mbedtls_pk_free(ctx);
6839+ os_free(ctx);
6840+ return NULL;
6841+}
6842+
6843+struct wpabuf * crypto_rsa_oaep_sha256_encrypt(struct crypto_rsa_key *key,
6844+ const struct wpabuf *in)
6845+{
6846+ mbedtls_rsa_context *pk_rsa = mbedtls_pk_rsa(*(mbedtls_pk_context*)key);
6847+ size_t olen = mbedtls_rsa_get_len(pk_rsa);
6848+ struct wpabuf *buf = wpabuf_alloc(olen);
6849+ if (buf == NULL)
6850+ return NULL;
6851+
6852+ /* mbedtls_pk_encrypt() takes a few more hops to get to same func */
6853+ if (mbedtls_rsa_rsaes_oaep_encrypt(pk_rsa,
6854+ mbedtls_ctr_drbg_random,
6855+ crypto_mbedtls_ctr_drbg(),
6856+ #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */
6857+ MBEDTLS_RSA_PRIVATE,
6858+ #endif
6859+ NULL, 0,
6860+ wpabuf_len(in), wpabuf_head(in),
6861+ wpabuf_put(buf, olen)) == 0) {
6862+ return buf;
6863+ }
6864+
6865+ wpabuf_clear_free(buf);
6866+ return NULL;
6867+}
6868+
6869+struct wpabuf * crypto_rsa_oaep_sha256_decrypt(struct crypto_rsa_key *key,
6870+ const struct wpabuf *in)
6871+{
6872+ mbedtls_rsa_context *pk_rsa = mbedtls_pk_rsa(*(mbedtls_pk_context*)key);
6873+ size_t olen = mbedtls_rsa_get_len(pk_rsa);
6874+ struct wpabuf *buf = wpabuf_alloc(olen);
6875+ if (buf == NULL)
6876+ return NULL;
6877+
6878+ /* mbedtls_pk_decrypt() takes a few more hops to get to same func */
6879+ if (mbedtls_rsa_rsaes_oaep_decrypt(pk_rsa,
6880+ mbedtls_ctr_drbg_random,
6881+ crypto_mbedtls_ctr_drbg(),
6882+ #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */
6883+ MBEDTLS_RSA_PUBLIC,
6884+ #endif
6885+ NULL, 0, &olen, wpabuf_head(in),
6886+ wpabuf_mhead(buf), olen) == 0) {
6887+ wpabuf_put(buf, olen);
6888+ return buf;
6889+ }
6890+
6891+ wpabuf_clear_free(buf);
6892+ return NULL;
6893+}
6894+
6895+void crypto_rsa_key_free(struct crypto_rsa_key *key)
6896+{
6897+ mbedtls_pk_free((mbedtls_pk_context *)key);
6898+ os_free(key);
6899+}
6900+
6901+#endif /* MBEDTLS_RSA_C */
6902+#endif /* CRYPTO_MBEDTLS_CRYPTO_RSA */
6903+
6904+#ifdef CRYPTO_MBEDTLS_CRYPTO_HPKE
6905+
6906+struct wpabuf * hpke_base_seal(enum hpke_kem_id kem_id,
6907+ enum hpke_kdf_id kdf_id,
6908+ enum hpke_aead_id aead_id,
6909+ struct crypto_ec_key *peer_pub,
6910+ const u8 *info, size_t info_len,
6911+ const u8 *aad, size_t aad_len,
6912+ const u8 *pt, size_t pt_len)
6913+{
6914+ /* not yet implemented */
6915+ return NULL;
6916+}
6917+
6918+struct wpabuf * hpke_base_open(enum hpke_kem_id kem_id,
6919+ enum hpke_kdf_id kdf_id,
6920+ enum hpke_aead_id aead_id,
6921+ struct crypto_ec_key *own_priv,
6922+ const u8 *info, size_t info_len,
6923+ const u8 *aad, size_t aad_len,
6924+ const u8 *enc_ct, size_t enc_ct_len)
6925+{
6926+ /* not yet implemented */
6927+ return NULL;
6928+}
6929+
6930+#endif
6931diff --git a/src/crypto/crypto_module_tests.c b/src/crypto/crypto_module_tests.c
6932index ffeddbadd..07c36d850 100644
6933--- a/src/crypto/crypto_module_tests.c
6934+++ b/src/crypto/crypto_module_tests.c
6935@@ -2470,6 +2470,139 @@ static int test_hpke(void)
6936 }
6937
6938
6939+static int test_ecc(void)
6940+{
6941+#ifdef CONFIG_ECC
6942+#ifndef CONFIG_TLS_INTERNAL
6943+#ifndef CONFIG_TLS_GNUTLS
6944+#if defined(CONFIG_TLS_MBEDTLS) \
6945+ || defined(CONFIG_TLS_OPENSSL) \
6946+ || defined(CONFIG_TLS_WOLFSSL)
6947+ wpa_printf(MSG_INFO, "Testing ECC");
6948+ /* Note: some tests below are valid on supported Short Weierstrass
6949+ * curves, but not on Montgomery curves (e.g. IKE groups 31 and 32)
6950+ * (e.g. deriving and comparing y^2 test below not valid on Montgomery)
6951+ */
6952+#ifdef CONFIG_TLS_MBEDTLS
6953+ const int grps[] = {19, 20, 21, 25, 26, 28};
6954+#endif
6955+#ifdef CONFIG_TLS_OPENSSL
6956+ const int grps[] = {19, 20, 21, 26};
6957+#endif
6958+#ifdef CONFIG_TLS_WOLFSSL
6959+ const int grps[] = {19, 20, 21, 26};
6960+#endif
6961+ uint32_t i;
6962+ struct crypto_ec *e = NULL;
6963+ struct crypto_ec_point *p = NULL, *q = NULL;
6964+ struct crypto_bignum *x = NULL, *y = NULL;
6965+#ifdef CONFIG_DPP
6966+ u8 bin[4096];
6967+#endif
6968+ for (i = 0; i < ARRAY_SIZE(grps); ++i) {
6969+ e = crypto_ec_init(grps[i]);
6970+ if (e == NULL
6971+ || crypto_ec_prime_len(e) == 0
6972+ || crypto_ec_prime_len_bits(e) == 0
6973+ || crypto_ec_order_len(e) == 0
6974+ || crypto_ec_get_prime(e) == NULL
6975+ || crypto_ec_get_order(e) == NULL
6976+ || crypto_ec_get_a(e) == NULL
6977+ || crypto_ec_get_b(e) == NULL
6978+ || crypto_ec_get_generator(e) == NULL) {
6979+ break;
6980+ }
6981+#ifdef CONFIG_DPP
6982+ struct crypto_ec_key *key = crypto_ec_key_gen(grps[i]);
6983+ if (key == NULL)
6984+ break;
6985+ p = crypto_ec_key_get_public_key(key);
6986+ q = crypto_ec_key_get_public_key(key);
6987+ crypto_ec_key_deinit(key);
6988+ if (p == NULL || q == NULL)
6989+ break;
6990+ if (!crypto_ec_point_is_on_curve(e, p))
6991+ break;
6992+
6993+ /* inverted point should not match original;
6994+ * double-invert should match */
6995+ if (crypto_ec_point_invert(e, q) != 0
6996+ || crypto_ec_point_cmp(e, p, q) == 0
6997+ || crypto_ec_point_invert(e, q) != 0
6998+ || crypto_ec_point_cmp(e, p, q) != 0) {
6999+ break;
7000+ }
7001+
7002+ /* crypto_ec_point_to_bin() and crypto_ec_point_from_bin()
7003+ * imbalanced interfaces? */
7004+ size_t prime_len = crypto_ec_prime_len(e);
7005+ if (prime_len * 2 > sizeof(bin))
7006+ break;
7007+ if (crypto_ec_point_to_bin(e, p, bin, bin+prime_len) != 0)
7008+ break;
7009+ struct crypto_ec_point *tmp = crypto_ec_point_from_bin(e, bin);
7010+ if (tmp == NULL)
7011+ break;
7012+ if (crypto_ec_point_cmp(e, p, tmp) != 0) {
7013+ crypto_ec_point_deinit(tmp, 0);
7014+ break;
7015+ }
7016+ crypto_ec_point_deinit(tmp, 0);
7017+
7018+ x = crypto_bignum_init();
7019+ y = crypto_bignum_init_set(bin+prime_len, prime_len);
7020+ if (x == NULL || y == NULL || crypto_ec_point_x(e, p, x) != 0)
7021+ break;
7022+ struct crypto_bignum *y2 = crypto_ec_point_compute_y_sqr(e, x);
7023+ if (y2 == NULL)
7024+ break;
7025+ if (crypto_bignum_sqrmod(y, crypto_ec_get_prime(e), y) != 0
7026+ || crypto_bignum_cmp(y, y2) != 0) {
7027+ crypto_bignum_deinit(y2, 0);
7028+ break;
7029+ }
7030+ crypto_bignum_deinit(y2, 0);
7031+ crypto_bignum_deinit(x, 0);
7032+ crypto_bignum_deinit(y, 0);
7033+ x = NULL;
7034+ y = NULL;
7035+
7036+ x = crypto_bignum_init();
7037+ if (x == NULL)
7038+ break;
7039+ if (crypto_bignum_rand(x, crypto_ec_get_prime(e)) != 0)
7040+ break;
7041+ crypto_bignum_deinit(x, 0);
7042+ x = NULL;
7043+
7044+ crypto_ec_point_deinit(p, 0);
7045+ p = NULL;
7046+ crypto_ec_point_deinit(q, 0);
7047+ q = NULL;
7048+#endif /* CONFIG_DPP */
7049+ crypto_ec_deinit(e);
7050+ e = NULL;
7051+ }
7052+ if (i != ARRAY_SIZE(grps)) {
7053+ crypto_bignum_deinit(x, 0);
7054+ crypto_bignum_deinit(y, 0);
7055+ crypto_ec_point_deinit(p, 0);
7056+ crypto_ec_point_deinit(q, 0);
7057+ crypto_ec_deinit(e);
7058+ wpa_printf(MSG_INFO,
7059+ "ECC test case failed tls_id:%d", grps[i]);
7060+ return -1;
7061+ }
7062+
7063+ wpa_printf(MSG_INFO, "ECC test cases passed");
7064+#endif
7065+#endif /* !CONFIG_TLS_GNUTLS */
7066+#endif /* !CONFIG_TLS_INTERNAL */
7067+#endif /* CONFIG_ECC */
7068+ return 0;
7069+}
7070+
7071+
7072 static int test_ms_funcs(void)
7073 {
7074 #ifndef CONFIG_FIPS
7075@@ -2591,6 +2724,7 @@ int crypto_module_tests(void)
7076 test_fips186_2_prf() ||
7077 test_extract_expand_hkdf() ||
7078 test_hpke() ||
7079+ test_ecc() ||
7080 test_ms_funcs())
7081 ret = -1;
7082
7083diff --git a/src/crypto/crypto_wolfssl.c b/src/crypto/crypto_wolfssl.c
7084index 269174321..a554fd8a8 100644
7085--- a/src/crypto/crypto_wolfssl.c
7086+++ b/src/crypto/crypto_wolfssl.c
7087@@ -1633,6 +1633,7 @@ struct crypto_ec {
7088 #ifdef CONFIG_DPP
7089 ecc_point *g; /* Only used in DPP for now */
7090 #endif /* CONFIG_DPP */
7091+ WC_RNG rng;
7092 mp_int a;
7093 mp_int prime;
7094 mp_int order;
7095@@ -1666,6 +1667,20 @@ struct crypto_ec * crypto_ec_init(int group)
7096 e->key = ecc_key_init();
7097 if (!e->key) {
7098 LOG_WOLF_ERROR_FUNC_NULL(ecc_key_init);
7099+
7100+ if (wc_ecc_init(e->key) != 0 ||
7101+ wc_InitRng(e->rng) != 0 ||
7102+ wc_ecc_set_rng(e->key, e->rng) != 0 ||
7103+ wc_ecc_set_curve(e->key, 0, curve_id) != 0 ||
7104+ mp_init(e->a) != MP_OKAY ||
7105+ mp_init(e->prime) != MP_OKAY ||
7106+ mp_init(e->order) != MP_OKAY ||
7107+ mp_init(e->b) != MP_OKAY ||
7108+ mp_read_radix(e->a, e->key.dp->Af, 16) != MP_OKAY ||
7109+ mp_read_radix(e->b, e->key.dp->Bf, 16) != MP_OKAY ||
7110+ mp_read_radix(e->prime, e->key.dp->prime, 16) != MP_OKAY ||
7111+ mp_read_radix(e->order, e->key.dp->order, 16) != MP_OKAY ||
7112+ mp_montgomery_setup(e->prime, e->mont_b) != MP_OKAY)
7113 goto done;
7114 }
7115
7116@@ -1764,6 +1779,9 @@ void crypto_ec_deinit(struct crypto_ec* e)
7117 #endif /* CONFIG_DPP */
7118 if (e->own_key)
7119 ecc_key_deinit(e->key);
7120+
7121+ wc_FreeRng(e->rng);
7122+ wc_ecc_free(e->key);
7123 os_free(e);
7124 }
7125
7126diff --git a/src/crypto/tls_mbedtls.c b/src/crypto/tls_mbedtls.c
7127new file mode 100644
7128index 000000000..2580a3a27
7129--- /dev/null
7130+++ b/src/crypto/tls_mbedtls.c
7131@@ -0,0 +1,3313 @@
7132+/*
7133+ * SSL/TLS interface functions for mbed TLS
7134+ *
7135+ * SPDX-FileCopyrightText: 2022 Glenn Strauss <gstrauss@gluelogic.com>
7136+ * SPDX-License-Identifier: BSD-3-Clause
7137+ *
7138+ * This software may be distributed under the terms of the BSD license.
7139+ * See README for more details.
7140+ *
7141+ * template: src/crypto/tls_none.c
7142+ * reference: src/crypto/tls_*.c
7143+ *
7144+ * Known Limitations:
7145+ * - no TLSv1.3 (not available in mbedtls 2.x; experimental in mbedtls 3.x)
7146+ * - no OCSP (not yet available in mbedtls)
7147+ * - mbedtls does not support all certificate encodings used by hwsim tests
7148+ * PCKS#5 v1.5
7149+ * PCKS#12
7150+ * DH DSA
7151+ * - EAP-FAST, EAP-TEAP session ticket support not implemented in tls_mbedtls.c
7152+ * - mbedtls does not currently provide way to set an attribute in a CSR
7153+ * https://github.com/Mbed-TLS/mbedtls/issues/4886
7154+ * so tests/hwsim dpp_enterprise tests fail
7155+ * - DPP2 not supported
7156+ * PKCS#7 parsing is not supported in mbedtls
7157+ * See crypto_mbedtls.c:crypto_pkcs7_get_certificates() comments
7158+ * - DPP3 not supported
7159+ * hpke_base_seal() and hpke_base_seal() not implemented in crypto_mbedtls.c
7160+ *
7161+ * Status:
7162+ * - code written to be compatible with mbedtls 2.x and mbedtls 3.x
7163+ * (currently requires mbedtls >= 2.27.0 for mbedtls_mpi_random())
7164+ * (currently requires mbedtls >= 2.18.0 for mbedtls_ssl_tls_prf())
7165+ * - builds with tests/build/build-wpa_supplicant-mbedtls.config
7166+ * - passes all tests/ crypto module tests (incomplete coverage)
7167+ * ($ cd tests; make clean; make -j 4 run-tests CONFIG_TLS=mbedtls)
7168+ * - passes almost all tests/hwsim tests
7169+ * (hwsim tests skipped for missing features)
7170+ *
7171+ * RFE:
7172+ * - EAP-FAST, EAP-TEAP session ticket support not implemented in tls_mbedtls.c
7173+ * - client/server session resumption, and/or save client session ticket
7174+ */
7175+
7176+#include "includes.h"
7177+#include "common.h"
7178+
7179+#include <mbedtls/version.h>
7180+#include <mbedtls/ctr_drbg.h>
7181+#include <mbedtls/error.h>
7182+#include <mbedtls/oid.h>
7183+#include <mbedtls/pem.h>
7184+#include <mbedtls/platform.h> /* mbedtls_calloc() mbedtls_free() */
7185+#include <mbedtls/platform_util.h> /* mbedtls_platform_zeroize() */
7186+#include <mbedtls/ssl.h>
7187+#include <mbedtls/ssl_ticket.h>
7188+#include <mbedtls/x509.h>
7189+#include <mbedtls/x509_crt.h>
7190+
7191+#if MBEDTLS_VERSION_NUMBER >= 0x02040000 /* mbedtls 2.4.0 */
7192+#include <mbedtls/net_sockets.h>
7193+#else
7194+#include <mbedtls/net.h>
7195+#endif
7196+
7197+#ifndef MBEDTLS_PRIVATE
7198+#define MBEDTLS_PRIVATE(x) x
7199+#endif
7200+
7201+#if MBEDTLS_VERSION_NUMBER < 0x03020000 /* mbedtls 3.2.0 */
7202+#define mbedtls_ssl_get_ciphersuite_id_from_ssl(ssl) \
7203+ ((ssl)->MBEDTLS_PRIVATE(session) \
7204+ ?(ssl)->MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(ciphersuite) \
7205+ : 0)
7206+#define mbedtls_ssl_ciphersuite_get_name(info) \
7207+ (info)->MBEDTLS_PRIVATE(name)
7208+#endif
7209+
7210+#include "crypto.h" /* sha256_vector() */
7211+#include "tls.h"
7212+
7213+#ifndef SHA256_DIGEST_LENGTH
7214+#define SHA256_DIGEST_LENGTH 32
7215+#endif
7216+
7217+#ifndef MBEDTLS_EXPKEY_FIXED_SECRET_LEN
7218+#define MBEDTLS_EXPKEY_FIXED_SECRET_LEN 48
7219+#endif
7220+
7221+#ifndef MBEDTLS_EXPKEY_RAND_LEN
7222+#define MBEDTLS_EXPKEY_RAND_LEN 32
7223+#endif
7224+
7225+#if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
7226+static mbedtls_ssl_export_keys_t tls_connection_export_keys_cb;
7227+#elif MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */
7228+static mbedtls_ssl_export_keys_ext_t tls_connection_export_keys_cb;
7229+#else /*(not implemented; return error)*/
7230+#define mbedtls_ssl_tls_prf(a,b,c,d,e,f,g,h) (-1)
7231+typedef mbedtls_tls_prf_types int;
7232+#endif
7233+
7234+
7235+/* hostapd/wpa_supplicant provides forced_memzero(),
7236+ * but prefer mbedtls_platform_zeroize() */
7237+#define forced_memzero(ptr,sz) mbedtls_platform_zeroize(ptr,sz)
7238+
7239+
7240+#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) \
7241+ || defined(EAP_TEAP) || defined(EAP_SERVER_TEAP)
7242+#ifdef MBEDTLS_SSL_SESSION_TICKETS
7243+#ifdef MBEDTLS_SSL_TICKET_C
7244+#define TLS_MBEDTLS_SESSION_TICKETS
7245+#if defined(EAP_TEAP) || defined(EAP_SERVER_TEAP)
7246+#define TLS_MBEDTLS_EAP_TEAP
7247+#endif
7248+#if !defined(CONFIG_FIPS) /* EAP-FAST keys cannot be exported in FIPS mode */
7249+#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST)
7250+#define TLS_MBEDTLS_EAP_FAST
7251+#endif
7252+#endif
7253+#endif
7254+#endif
7255+#endif
7256+
7257+
7258+struct tls_conf {
7259+ mbedtls_ssl_config conf;
7260+
7261+ unsigned int verify_peer:1;
7262+ unsigned int verify_depth0_only:1;
7263+ unsigned int check_crl:2; /*(needs :2 bits for 0, 1, 2)*/
7264+ unsigned int check_crl_strict:1; /*(needs :1 bit for 0, 1)*/
7265+ unsigned int ca_cert_probe:1;
7266+ unsigned int has_ca_cert:1;
7267+ unsigned int has_client_cert:1;
7268+ unsigned int has_private_key:1;
7269+ unsigned int suiteb128:1;
7270+ unsigned int suiteb192:1;
7271+ mbedtls_x509_crl *crl;
7272+ mbedtls_x509_crt ca_cert;
7273+ mbedtls_x509_crt client_cert;
7274+ mbedtls_pk_context private_key;
7275+
7276+ uint32_t refcnt;
7277+
7278+ unsigned int flags;
7279+ char *subject_match;
7280+ char *altsubject_match;
7281+ char *suffix_match;
7282+ char *domain_match;
7283+ char *check_cert_subject;
7284+ u8 ca_cert_hash[SHA256_DIGEST_LENGTH];
7285+
7286+ int *ciphersuites; /* list of ciphersuite ids for mbedtls_ssl_config */
7287+#if MBEDTLS_VERSION_NUMBER < 0x03010000 /* mbedtls 3.1.0 */
7288+ mbedtls_ecp_group_id *curves;
7289+#else
7290+ uint16_t *curves; /* list of curve ids for mbedtls_ssl_config */
7291+#endif
7292+};
7293+
7294+
7295+struct tls_global {
7296+ struct tls_conf *tls_conf;
7297+ char *ocsp_stapling_response;
7298+ mbedtls_ctr_drbg_context *ctr_drbg; /*(see crypto_mbedtls.c)*/
7299+ #ifdef MBEDTLS_SSL_SESSION_TICKETS
7300+ mbedtls_ssl_ticket_context ticket_ctx;
7301+ #endif
7302+ char *ca_cert_file;
7303+ struct os_reltime crl_reload_previous;
7304+ unsigned int crl_reload_interval;
7305+ uint32_t refcnt;
7306+ struct tls_config init_conf;
7307+};
7308+
7309+static struct tls_global tls_ctx_global;
7310+
7311+
7312+struct tls_connection {
7313+ struct tls_conf *tls_conf;
7314+ struct wpabuf *push_buf;
7315+ struct wpabuf *pull_buf;
7316+ size_t pull_buf_offset;
7317+
7318+ unsigned int established:1;
7319+ unsigned int resumed:1;
7320+ unsigned int verify_peer:1;
7321+ unsigned int is_server:1;
7322+
7323+ mbedtls_ssl_context ssl;
7324+
7325+ mbedtls_tls_prf_types tls_prf_type;
7326+ size_t expkey_keyblock_size;
7327+ size_t expkey_secret_len;
7328+ #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */
7329+ unsigned char expkey_secret[MBEDTLS_EXPKEY_FIXED_SECRET_LEN];
7330+ #else
7331+ unsigned char expkey_secret[MBEDTLS_MD_MAX_SIZE];
7332+ #endif
7333+ unsigned char expkey_randbytes[MBEDTLS_EXPKEY_RAND_LEN*2];
7334+
7335+ int read_alerts, write_alerts, failed;
7336+
7337+ #ifdef TLS_MBEDTLS_SESSION_TICKETS
7338+ tls_session_ticket_cb session_ticket_cb;
7339+ void *session_ticket_cb_ctx;
7340+ unsigned char *clienthello_session_ticket;
7341+ size_t clienthello_session_ticket_len;
7342+ #endif
7343+ char *peer_subject; /* peer subject info for authenticated peer */
7344+ struct wpabuf *success_data;
7345+};
7346+
7347+
7348+#ifndef __has_attribute
7349+#define __has_attribute(x) 0
7350+#endif
7351+
7352+#ifndef __GNUC_PREREQ
7353+#define __GNUC_PREREQ(maj,min) 0
7354+#endif
7355+
7356+#ifndef __attribute_cold__
7357+#if __has_attribute(cold) \
7358+ || __GNUC_PREREQ(4,3)
7359+#define __attribute_cold__ __attribute__((__cold__))
7360+#else
7361+#define __attribute_cold__
7362+#endif
7363+#endif
7364+
7365+#ifndef __attribute_noinline__
7366+#if __has_attribute(noinline) \
7367+ || __GNUC_PREREQ(3,1)
7368+#define __attribute_noinline__ __attribute__((__noinline__))
7369+#else
7370+#define __attribute_noinline__
7371+#endif
7372+#endif
7373+
7374+
7375+__attribute_cold__
7376+__attribute_noinline__
7377+static void emsg(int level, const char * const msg)
7378+{
7379+ wpa_printf(level, "MTLS: %s", msg);
7380+}
7381+
7382+
7383+__attribute_cold__
7384+__attribute_noinline__
7385+static void emsgrc(int level, const char * const msg, int rc)
7386+{
7387+ #ifdef MBEDTLS_ERROR_C
7388+ /* error logging convenience function that decodes mbedtls result codes */
7389+ char buf[256];
7390+ mbedtls_strerror(rc, buf, sizeof(buf));
7391+ wpa_printf(level, "MTLS: %s: %s (-0x%04x)", msg, buf, -rc);
7392+ #else
7393+ wpa_printf(level, "MTLS: %s: (-0x%04x)", msg, -rc);
7394+ #endif
7395+}
7396+
7397+
7398+#define elog(rc, msg) emsgrc(MSG_ERROR, (msg), (rc))
7399+#define ilog(rc, msg) emsgrc(MSG_INFO, (msg), (rc))
7400+
7401+
7402+struct tls_conf * tls_conf_init(void *tls_ctx)
7403+{
7404+ struct tls_conf *tls_conf = os_zalloc(sizeof(*tls_conf));
7405+ if (tls_conf == NULL)
7406+ return NULL;
7407+ tls_conf->refcnt = 1;
7408+
7409+ mbedtls_ssl_config_init(&tls_conf->conf);
7410+ mbedtls_ssl_conf_rng(&tls_conf->conf,
7411+ mbedtls_ctr_drbg_random, tls_ctx_global.ctr_drbg);
7412+ mbedtls_x509_crt_init(&tls_conf->ca_cert);
7413+ mbedtls_x509_crt_init(&tls_conf->client_cert);
7414+ mbedtls_pk_init(&tls_conf->private_key);
7415+
7416+ return tls_conf;
7417+}
7418+
7419+
7420+void tls_conf_deinit(struct tls_conf *tls_conf)
7421+{
7422+ if (tls_conf == NULL || --tls_conf->refcnt != 0)
7423+ return;
7424+
7425+ mbedtls_x509_crt_free(&tls_conf->ca_cert);
7426+ mbedtls_x509_crt_free(&tls_conf->client_cert);
7427+ if (tls_conf->crl) {
7428+ mbedtls_x509_crl_free(tls_conf->crl);
7429+ os_free(tls_conf->crl);
7430+ }
7431+ mbedtls_pk_free(&tls_conf->private_key);
7432+ mbedtls_ssl_config_free(&tls_conf->conf);
7433+ os_free(tls_conf->curves);
7434+ os_free(tls_conf->ciphersuites);
7435+ os_free(tls_conf->subject_match);
7436+ os_free(tls_conf->altsubject_match);
7437+ os_free(tls_conf->suffix_match);
7438+ os_free(tls_conf->domain_match);
7439+ os_free(tls_conf->check_cert_subject);
7440+ os_free(tls_conf);
7441+}
7442+
7443+
7444+mbedtls_ctr_drbg_context * crypto_mbedtls_ctr_drbg(void); /*(not in header)*/
7445+
7446+__attribute_cold__
7447+void * tls_init(const struct tls_config *conf)
7448+{
7449+ /* RFE: review struct tls_config *conf (different from tls_conf) */
7450+
7451+ if (++tls_ctx_global.refcnt > 1)
7452+ return &tls_ctx_global;
7453+
7454+ tls_ctx_global.ctr_drbg = crypto_mbedtls_ctr_drbg();
7455+ #ifdef MBEDTLS_SSL_SESSION_TICKETS
7456+ mbedtls_ssl_ticket_init(&tls_ctx_global.ticket_ctx);
7457+ mbedtls_ssl_ticket_setup(&tls_ctx_global.ticket_ctx,
7458+ mbedtls_ctr_drbg_random,
7459+ tls_ctx_global.ctr_drbg,
7460+ MBEDTLS_CIPHER_AES_256_GCM,
7461+ 43200); /* ticket timeout: 12 hours */
7462+ #endif
7463+ /* copy struct for future use */
7464+ tls_ctx_global.init_conf = *conf;
7465+ if (conf->openssl_ciphers)
7466+ tls_ctx_global.init_conf.openssl_ciphers =
7467+ os_strdup(conf->openssl_ciphers);
7468+
7469+ tls_ctx_global.crl_reload_interval = conf->crl_reload_interval;
7470+ os_get_reltime(&tls_ctx_global.crl_reload_previous);
7471+
7472+ return &tls_ctx_global;
7473+}
7474+
7475+
7476+__attribute_cold__
7477+void tls_deinit(void *tls_ctx)
7478+{
7479+ if (tls_ctx == NULL || --tls_ctx_global.refcnt != 0)
7480+ return;
7481+
7482+ tls_conf_deinit(tls_ctx_global.tls_conf);
7483+ os_free(tls_ctx_global.ca_cert_file);
7484+ os_free(tls_ctx_global.ocsp_stapling_response);
7485+ char *openssl_ciphers; /*(allocated in tls_init())*/
7486+ *(const char **)&openssl_ciphers =
7487+ tls_ctx_global.init_conf.openssl_ciphers;
7488+ os_free(openssl_ciphers);
7489+ #ifdef MBEDTLS_SSL_SESSION_TICKETS
7490+ mbedtls_ssl_ticket_free(&tls_ctx_global.ticket_ctx);
7491+ #endif
7492+ os_memset(&tls_ctx_global, 0, sizeof(tls_ctx_global));
7493+}
7494+
7495+
7496+int tls_get_errors(void *tls_ctx)
7497+{
7498+ return 0;
7499+}
7500+
7501+
7502+static void tls_connection_deinit_expkey(struct tls_connection *conn)
7503+{
7504+ conn->tls_prf_type = 0; /* MBEDTLS_SSL_TLS_PRF_NONE; */
7505+ conn->expkey_keyblock_size = 0;
7506+ conn->expkey_secret_len = 0;
7507+ forced_memzero(conn->expkey_secret, sizeof(conn->expkey_secret));
7508+ forced_memzero(conn->expkey_randbytes, sizeof(conn->expkey_randbytes));
7509+}
7510+
7511+
7512+#ifdef TLS_MBEDTLS_SESSION_TICKETS
7513+void tls_connection_deinit_clienthello_session_ticket(struct tls_connection *conn)
7514+{
7515+ if (conn->clienthello_session_ticket) {
7516+ mbedtls_platform_zeroize(conn->clienthello_session_ticket,
7517+ conn->clienthello_session_ticket_len);
7518+ mbedtls_free(conn->clienthello_session_ticket);
7519+ conn->clienthello_session_ticket = NULL;
7520+ conn->clienthello_session_ticket_len = 0;
7521+ }
7522+}
7523+#endif
7524+
7525+
7526+void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn)
7527+{
7528+ if (conn == NULL)
7529+ return;
7530+
7531+ #if 0 /*(good intention, but never sent since we destroy self below)*/
7532+ if (conn->established)
7533+ mbedtls_ssl_close_notify(&conn->ssl);
7534+ #endif
7535+
7536+ if (conn->tls_prf_type)
7537+ tls_connection_deinit_expkey(conn);
7538+
7539+ #ifdef TLS_MBEDTLS_SESSION_TICKETS
7540+ if (conn->clienthello_session_ticket)
7541+ tls_connection_deinit_clienthello_session_ticket(conn);
7542+ #endif
7543+
7544+ os_free(conn->peer_subject);
7545+ wpabuf_free(conn->success_data);
7546+ wpabuf_free(conn->push_buf);
7547+ wpabuf_free(conn->pull_buf);
7548+ mbedtls_ssl_free(&conn->ssl);
7549+ tls_conf_deinit(conn->tls_conf);
7550+ os_free(conn);
7551+}
7552+
7553+
7554+static void tls_mbedtls_refresh_crl(void);
7555+static int tls_mbedtls_ssl_setup(struct tls_connection *conn);
7556+
7557+struct tls_connection * tls_connection_init(void *tls_ctx)
7558+{
7559+ struct tls_connection *conn = os_zalloc(sizeof(*conn));
7560+ if (conn == NULL)
7561+ return NULL;
7562+
7563+ mbedtls_ssl_init(&conn->ssl);
7564+
7565+ conn->tls_conf = tls_ctx_global.tls_conf; /*(inherit global conf, if set)*/
7566+ if (conn->tls_conf) {
7567+ ++conn->tls_conf->refcnt;
7568+ /* check for CRL refresh if inheriting from global config */
7569+ tls_mbedtls_refresh_crl();
7570+
7571+ conn->verify_peer = conn->tls_conf->verify_peer;
7572+ if (tls_mbedtls_ssl_setup(conn) != 0) {
7573+ tls_connection_deinit(&tls_ctx_global, conn);
7574+ return NULL;
7575+ }
7576+ }
7577+
7578+ return conn;
7579+}
7580+
7581+
7582+int tls_connection_established(void *tls_ctx, struct tls_connection *conn)
7583+{
7584+ return conn ? conn->established : 0;
7585+}
7586+
7587+
7588+__attribute_noinline__
7589+char * tls_mbedtls_peer_serial_num(const mbedtls_x509_crt *crt, char *serial_num, size_t len)
7590+{
7591+ /* mbedtls_x509_serial_gets() inefficiently formats to hex separated by
7592+ * colons, so generate the hex serial number here. The func
7593+ * wpa_snprintf_hex_uppercase() is similarly inefficient. */
7594+ size_t i = 0; /* skip leading 0's per Distinguished Encoding Rules (DER) */
7595+ while (i < crt->serial.len && crt->serial.p[i] == 0) ++i;
7596+ if (i == crt->serial.len) --i;
7597+
7598+ const unsigned char *s = crt->serial.p + i;
7599+ const size_t e = (crt->serial.len - i) * 2;
7600+ if (e >= len)
7601+ return NULL;
7602+ #if 0
7603+ wpa_snprintf_hex_uppercase(serial_num, len, s, crt->serial.len-i);
7604+ #else
7605+ for (i = 0; i < e; i+=2, ++s) {
7606+ serial_num[i+0] = "0123456789ABCDEF"[(*s >> 4)];
7607+ serial_num[i+1] = "0123456789ABCDEF"[(*s & 0xF)];
7608+ }
7609+ serial_num[e] = '\0';
7610+ #endif
7611+ return serial_num;
7612+}
7613+
7614+
7615+char * tls_connection_peer_serial_num(void *tls_ctx,
7616+ struct tls_connection *conn)
7617+{
7618+ const mbedtls_x509_crt *crt = mbedtls_ssl_get_peer_cert(&conn->ssl);
7619+ if (crt == NULL)
7620+ return NULL;
7621+ size_t len = crt->serial.len * 2 + 1;
7622+ char *serial_num = os_malloc(len);
7623+ if (!serial_num)
7624+ return NULL;
7625+ return tls_mbedtls_peer_serial_num(crt, serial_num, len);
7626+}
7627+
7628+
7629+static void tls_pull_buf_reset(struct tls_connection *conn);
7630+
7631+int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn)
7632+{
7633+ /* Note: this function called from eap_peer_tls_reauth_init()
7634+ * for session resumption, not for connection shutdown */
7635+
7636+ if (conn == NULL)
7637+ return -1;
7638+
7639+ tls_pull_buf_reset(conn);
7640+ wpabuf_free(conn->push_buf);
7641+ conn->push_buf = NULL;
7642+ conn->established = 0;
7643+ conn->resumed = 0;
7644+ if (conn->tls_prf_type)
7645+ tls_connection_deinit_expkey(conn);
7646+
7647+ /* RFE: prepare for session resumption? (see doc in crypto/tls.h) */
7648+
7649+ return mbedtls_ssl_session_reset(&conn->ssl);
7650+}
7651+
7652+
7653+static int tls_wpabuf_resize_put_data(struct wpabuf **buf,
7654+ const unsigned char *data, size_t dlen)
7655+{
7656+ if (wpabuf_resize(buf, dlen) < 0)
7657+ return 0;
7658+ wpabuf_put_data(*buf, data, dlen);
7659+ return 1;
7660+}
7661+
7662+
7663+static int tls_pull_buf_append(struct tls_connection *conn,
7664+ const struct wpabuf *in_data)
7665+{
7666+ /*(interface does not lend itself to move semantics)*/
7667+ return tls_wpabuf_resize_put_data(&conn->pull_buf,
7668+ wpabuf_head(in_data),
7669+ wpabuf_len(in_data));
7670+}
7671+
7672+
7673+static void tls_pull_buf_reset(struct tls_connection *conn)
7674+{
7675+ /*(future: might consider reusing conn->pull_buf)*/
7676+ wpabuf_free(conn->pull_buf);
7677+ conn->pull_buf = NULL;
7678+ conn->pull_buf_offset = 0;
7679+}
7680+
7681+
7682+__attribute_cold__
7683+static void tls_pull_buf_discard(struct tls_connection *conn, const char *func)
7684+{
7685+ size_t discard = wpabuf_len(conn->pull_buf) - conn->pull_buf_offset;
7686+ if (discard)
7687+ wpa_printf(MSG_DEBUG,
7688+ "%s - %zu bytes remaining in pull_buf; discarding",
7689+ func, discard);
7690+ tls_pull_buf_reset(conn);
7691+}
7692+
7693+
7694+static int tls_pull_func(void *ptr, unsigned char *buf, size_t len)
7695+{
7696+ struct tls_connection *conn = (struct tls_connection *) ptr;
7697+ if (conn->pull_buf == NULL)
7698+ return MBEDTLS_ERR_SSL_WANT_READ;
7699+ const size_t dlen = wpabuf_len(conn->pull_buf) - conn->pull_buf_offset;
7700+ if (dlen == 0)
7701+ return MBEDTLS_ERR_SSL_WANT_READ;
7702+
7703+ if (len > dlen)
7704+ len = dlen;
7705+ os_memcpy(buf, wpabuf_head(conn->pull_buf)+conn->pull_buf_offset, len);
7706+
7707+ if (len == dlen) {
7708+ tls_pull_buf_reset(conn);
7709+ /*wpa_printf(MSG_DEBUG, "%s - emptied pull_buf", __func__);*/
7710+ }
7711+ else {
7712+ conn->pull_buf_offset += len;
7713+ /*wpa_printf(MSG_DEBUG, "%s - %zu bytes remaining in pull_buf",
7714+ __func__, dlen - len);*/
7715+ }
7716+ return (int)len;
7717+}
7718+
7719+
7720+static int tls_push_func(void *ptr, const unsigned char *buf, size_t len)
7721+{
7722+ struct tls_connection *conn = (struct tls_connection *) ptr;
7723+ return tls_wpabuf_resize_put_data(&conn->push_buf, buf, len)
7724+ ? (int)len
7725+ : MBEDTLS_ERR_SSL_ALLOC_FAILED;
7726+}
7727+
7728+
7729+static int
7730+tls_mbedtls_verify_cb (void *arg, mbedtls_x509_crt *crt, int depth, uint32_t *flags);
7731+
7732+
7733+static int tls_mbedtls_ssl_setup(struct tls_connection *conn)
7734+{
7735+ #if 0
7736+ /* mbedtls_ssl_setup() must be called only once */
7737+ /* If this func might be called multiple times (e.g. via set_params),
7738+ * then we should set a flag in conn that ssl was initialized */
7739+ if (conn->ssl_is_init) {
7740+ mbedtls_ssl_free(&conn->ssl);
7741+ mbedtls_ssl_init(&conn->ssl);
7742+ }
7743+ #endif
7744+
7745+ int ret = mbedtls_ssl_setup(&conn->ssl, &conn->tls_conf->conf);
7746+ if (ret != 0) {
7747+ elog(ret, "mbedtls_ssl_setup");
7748+ return -1;
7749+ }
7750+
7751+ mbedtls_ssl_set_bio(&conn->ssl, conn, tls_push_func, tls_pull_func, NULL);
7752+ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
7753+ mbedtls_ssl_set_export_keys_cb(
7754+ &conn->ssl, tls_connection_export_keys_cb, conn);
7755+ #elif MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */
7756+ mbedtls_ssl_conf_export_keys_ext_cb(
7757+ &conn->tls_conf->conf, tls_connection_export_keys_cb, conn);
7758+ #endif
7759+ if (conn->verify_peer)
7760+ mbedtls_ssl_set_verify(&conn->ssl, tls_mbedtls_verify_cb, conn);
7761+
7762+ return 0;
7763+}
7764+
7765+
7766+static int tls_mbedtls_data_is_pem(const u8 *data)
7767+{
7768+ return (NULL != os_strstr((char *)data, "-----"));
7769+}
7770+
7771+
7772+static void tls_mbedtls_set_allowed_tls_vers(struct tls_conf *tls_conf,
7773+ mbedtls_ssl_config *conf)
7774+{
7775+ #if !defined(MBEDTLS_SSL_PROTO_TLS1_3)
7776+ tls_conf->flags |= TLS_CONN_DISABLE_TLSv1_3;
7777+ #endif
7778+
7779+ /* unconditionally require TLSv1.2+ for TLS_CONN_SUITEB */
7780+ if (tls_conf->flags & TLS_CONN_SUITEB) {
7781+ tls_conf->flags |= TLS_CONN_DISABLE_TLSv1_0;
7782+ tls_conf->flags |= TLS_CONN_DISABLE_TLSv1_1;
7783+ }
7784+
7785+ const unsigned int flags = tls_conf->flags;
7786+
7787+ /* attempt to map flags to min and max TLS protocol version */
7788+
7789+ int min = (flags & TLS_CONN_DISABLE_TLSv1_0)
7790+ ? (flags & TLS_CONN_DISABLE_TLSv1_1)
7791+ ? (flags & TLS_CONN_DISABLE_TLSv1_2)
7792+ ? (flags & TLS_CONN_DISABLE_TLSv1_3)
7793+ ? 4
7794+ : 3
7795+ : 2
7796+ : 1
7797+ : 0;
7798+
7799+ int max = (flags & TLS_CONN_DISABLE_TLSv1_3)
7800+ ? (flags & TLS_CONN_DISABLE_TLSv1_2)
7801+ ? (flags & TLS_CONN_DISABLE_TLSv1_1)
7802+ ? (flags & TLS_CONN_DISABLE_TLSv1_0)
7803+ ? -1
7804+ : 0
7805+ : 1
7806+ : 2
7807+ : 3;
7808+
7809+ if ((flags & TLS_CONN_ENABLE_TLSv1_2) && min > 2) min = 2;
7810+ if ((flags & TLS_CONN_ENABLE_TLSv1_1) && min > 1) min = 1;
7811+ if ((flags & TLS_CONN_ENABLE_TLSv1_0) && min > 0) min = 0;
7812+ if (max < min) {
7813+ emsg(MSG_ERROR, "invalid tls_disable_tlsv* params; ignoring");
7814+ return;
7815+ }
7816+ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
7817+ /* mbed TLS 3.0.0 removes support for protocols < TLSv1.2 */
7818+ if (min < 2 || max < 2) {
7819+ emsg(MSG_ERROR, "invalid tls_disable_tlsv* params; ignoring");
7820+ if (min < 2) min = 2;
7821+ if (max < 2) max = 2;
7822+ }
7823+ #endif
7824+
7825+ #if MBEDTLS_VERSION_NUMBER >= 0x03020000 /* mbedtls 3.2.0 */
7826+ /* MBEDTLS_SSL_VERSION_TLS1_2 = 0x0303 *//*!< (D)TLS 1.2 */
7827+ /* MBEDTLS_SSL_VERSION_TLS1_3 = 0x0304 *//*!< (D)TLS 1.3 */
7828+ min = (min == 2) ? MBEDTLS_SSL_VERSION_TLS1_2 : MBEDTLS_SSL_VERSION_TLS1_3;
7829+ max = (max == 2) ? MBEDTLS_SSL_VERSION_TLS1_2 : MBEDTLS_SSL_VERSION_TLS1_3;
7830+ mbedtls_ssl_conf_min_tls_version(conf, min);
7831+ mbedtls_ssl_conf_max_tls_version(conf, max);
7832+ #else
7833+ #ifndef MBEDTLS_SSL_MINOR_VERSION_4
7834+ if (min == 3) min = 2;
7835+ if (max == 3) max = 2;
7836+ #endif
7837+ /* MBEDTLS_SSL_MINOR_VERSION_0 0 *//*!< SSL v3.0 */
7838+ /* MBEDTLS_SSL_MINOR_VERSION_1 1 *//*!< TLS v1.0 */
7839+ /* MBEDTLS_SSL_MINOR_VERSION_2 2 *//*!< TLS v1.1 */
7840+ /* MBEDTLS_SSL_MINOR_VERSION_3 3 *//*!< TLS v1.2 */
7841+ /* MBEDTLS_SSL_MINOR_VERSION_4 4 *//*!< TLS v1.3 */
7842+ mbedtls_ssl_conf_min_version(conf, MBEDTLS_SSL_MAJOR_VERSION_3, min+1);
7843+ mbedtls_ssl_conf_max_version(conf, MBEDTLS_SSL_MAJOR_VERSION_3, max+1);
7844+ #endif
7845+}
7846+
7847+
7848+__attribute_noinline__
7849+static int tls_mbedtls_readfile(const char *path, u8 **buf, size_t *n);
7850+
7851+
7852+static int
7853+tls_mbedtls_set_dhparams(struct tls_conf *tls_conf, const char *dh_file)
7854+{
7855+ size_t len;
7856+ u8 *data;
7857+ if (tls_mbedtls_readfile(dh_file, &data, &len))
7858+ return 0;
7859+
7860+ /* parse only if DH parameters if in PEM format */
7861+ if (tls_mbedtls_data_is_pem(data)
7862+ && NULL == os_strstr((char *)data, "-----BEGIN DH PARAMETERS-----")) {
7863+ if (os_strstr((char *)data, "-----BEGIN DSA PARAMETERS-----"))
7864+ wpa_printf(MSG_WARNING, "DSA parameters not handled (%s)", dh_file);
7865+ else
7866+ wpa_printf(MSG_WARNING, "unexpected DH param content (%s)",dh_file);
7867+ forced_memzero(data, len);
7868+ os_free(data);
7869+ return 0;
7870+ }
7871+
7872+ /* mbedtls_dhm_parse_dhm() expects "-----BEGIN DH PARAMETERS-----" if PEM */
7873+ mbedtls_dhm_context dhm;
7874+ mbedtls_dhm_init(&dhm);
7875+ int rc = mbedtls_dhm_parse_dhm(&dhm, data, len);
7876+ if (0 == rc)
7877+ rc = mbedtls_ssl_conf_dh_param_ctx(&tls_conf->conf, &dhm);
7878+ if (0 != rc)
7879+ elog(rc, dh_file);
7880+ mbedtls_dhm_free(&dhm);
7881+
7882+ forced_memzero(data, len);
7883+ os_free(data);
7884+ return (0 == rc);
7885+}
7886+
7887+
7888+/* reference: lighttpd src/mod_mbedtls.c:mod_mbedtls_ssl_append_curve()
7889+ * (same author: gstrauss@gluelogic.com; same license: BSD-3-Clause) */
7890+#if MBEDTLS_VERSION_NUMBER < 0x03010000 /* mbedtls 3.1.0 */
7891+static int
7892+tls_mbedtls_append_curve (mbedtls_ecp_group_id *ids, int nids, int idsz, const mbedtls_ecp_group_id id)
7893+{
7894+ if (1 >= idsz - (nids + 1)) {
7895+ emsg(MSG_ERROR, "error: too many curves during list expand");
7896+ return -1;
7897+ }
7898+ ids[++nids] = id;
7899+ return nids;
7900+}
7901+
7902+
7903+static int
7904+tls_mbedtls_set_curves(struct tls_conf *tls_conf, const char *curvelist)
7905+{
7906+ mbedtls_ecp_group_id ids[512];
7907+ int nids = -1;
7908+ const int idsz = (int)(sizeof(ids)/sizeof(*ids)-1);
7909+ const mbedtls_ecp_curve_info * const curve_info = mbedtls_ecp_curve_list();
7910+
7911+ for (const char *e = curvelist-1; e; ) {
7912+ const char * const n = e+1;
7913+ e = os_strchr(n, ':');
7914+ size_t len = e ? (size_t)(e - n) : os_strlen(n);
7915+ mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE;
7916+ switch (len) {
7917+ case 5:
7918+ if (0 == os_memcmp("P-521", n, 5))
7919+ grp_id = MBEDTLS_ECP_DP_SECP521R1;
7920+ else if (0 == os_memcmp("P-384", n, 5))
7921+ grp_id = MBEDTLS_ECP_DP_SECP384R1;
7922+ else if (0 == os_memcmp("P-256", n, 5))
7923+ grp_id = MBEDTLS_ECP_DP_SECP256R1;
7924+ break;
7925+ case 6:
7926+ if (0 == os_memcmp("BP-521", n, 6))
7927+ grp_id = MBEDTLS_ECP_DP_BP512R1;
7928+ else if (0 == os_memcmp("BP-384", n, 6))
7929+ grp_id = MBEDTLS_ECP_DP_BP384R1;
7930+ else if (0 == os_memcmp("BP-256", n, 6))
7931+ grp_id = MBEDTLS_ECP_DP_BP256R1;
7932+ break;
7933+ default:
7934+ break;
7935+ }
7936+ if (grp_id != MBEDTLS_ECP_DP_NONE) {
7937+ nids = tls_mbedtls_append_curve(ids, nids, idsz, grp_id);
7938+ if (-1 == nids) return 0;
7939+ continue;
7940+ }
7941+ /* similar to mbedtls_ecp_curve_info_from_name() */
7942+ const mbedtls_ecp_curve_info *info;
7943+ for (info = curve_info; info->grp_id != MBEDTLS_ECP_DP_NONE; ++info) {
7944+ if (0 == os_strncmp(info->name, n, len) && info->name[len] == '\0')
7945+ break;
7946+ }
7947+ if (info->grp_id == MBEDTLS_ECP_DP_NONE) {
7948+ wpa_printf(MSG_ERROR, "MTLS: unrecognized curve: %.*s",(int)len,n);
7949+ return 0;
7950+ }
7951+
7952+ nids = tls_mbedtls_append_curve(ids, nids, idsz, info->grp_id);
7953+ if (-1 == nids) return 0;
7954+ }
7955+
7956+ /* mod_openssl configures "prime256v1" if curve list not specified,
7957+ * but mbedtls provides a list of supported curves if not explicitly set */
7958+ if (-1 == nids) return 1; /* empty list; no-op */
7959+
7960+ ids[++nids] = MBEDTLS_ECP_DP_NONE; /* terminate list */
7961+ ++nids;
7962+
7963+ /* curves list must be persistent for lifetime of mbedtls_ssl_config */
7964+ tls_conf->curves = os_malloc(nids * sizeof(mbedtls_ecp_group_id));
7965+ if (tls_conf->curves == NULL)
7966+ return 0;
7967+ os_memcpy(tls_conf->curves, ids, nids * sizeof(mbedtls_ecp_group_id));
7968+
7969+ mbedtls_ssl_conf_curves(&tls_conf->conf, tls_conf->curves);
7970+ return 1;
7971+}
7972+#else
7973+static int
7974+tls_mbedtls_append_curve (uint16_t *ids, int nids, int idsz, const uint16_t id)
7975+{
7976+ if (1 >= idsz - (nids + 1)) {
7977+ emsg(MSG_ERROR, "error: too many curves during list expand");
7978+ return -1;
7979+ }
7980+ ids[++nids] = id;
7981+ return nids;
7982+}
7983+
7984+
7985+static int
7986+tls_mbedtls_set_curves(struct tls_conf *tls_conf, const char *curvelist)
7987+{
7988+ /* TLS Supported Groups (renamed from "EC Named Curve Registry")
7989+ * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8
7990+ */
7991+ uint16_t ids[512];
7992+ int nids = -1;
7993+ const int idsz = (int)(sizeof(ids)/sizeof(*ids)-1);
7994+ const mbedtls_ecp_curve_info * const curve_info = mbedtls_ecp_curve_list();
7995+
7996+ for (const char *e = curvelist-1; e; ) {
7997+ const char * const n = e+1;
7998+ e = os_strchr(n, ':');
7999+ size_t len = e ? (size_t)(e - n) : os_strlen(n);
8000+ uint16_t tls_id = 0;
8001+ switch (len) {
8002+ case 5:
8003+ if (0 == os_memcmp("P-521", n, 5))
8004+ tls_id = 25; /* mbedtls_ecp_group_id MBEDTLS_ECP_DP_SECP521R1 */
8005+ else if (0 == os_memcmp("P-384", n, 5))
8006+ tls_id = 24; /* mbedtls_ecp_group_id MBEDTLS_ECP_DP_SECP384R1 */
8007+ else if (0 == os_memcmp("P-256", n, 5))
8008+ tls_id = 23; /* mbedtls_ecp_group_id MBEDTLS_ECP_DP_SECP256R1 */
8009+ break;
8010+ case 6:
8011+ if (0 == os_memcmp("BP-521", n, 6))
8012+ tls_id = 28; /* mbedtls_ecp_group_id MBEDTLS_ECP_DP_BP512R1 */
8013+ else if (0 == os_memcmp("BP-384", n, 6))
8014+ tls_id = 27; /* mbedtls_ecp_group_id MBEDTLS_ECP_DP_BP384R1 */
8015+ else if (0 == os_memcmp("BP-256", n, 6))
8016+ tls_id = 26; /* mbedtls_ecp_group_id MBEDTLS_ECP_DP_BP256R1 */
8017+ break;
8018+ default:
8019+ break;
8020+ }
8021+ if (tls_id != 0) {
8022+ nids = tls_mbedtls_append_curve(ids, nids, idsz, tls_id);
8023+ if (-1 == nids) return 0;
8024+ continue;
8025+ }
8026+ /* similar to mbedtls_ecp_curve_info_from_name() */
8027+ const mbedtls_ecp_curve_info *info;
8028+ for (info = curve_info; info->tls_id != 0; ++info) {
8029+ if (0 == os_strncmp(info->name, n, len) && info->name[len] == '\0')
8030+ break;
8031+ }
8032+ if (info->tls_id == 0) {
8033+ wpa_printf(MSG_ERROR, "MTLS: unrecognized curve: %.*s",(int)len,n);
8034+ return 0;
8035+ }
8036+
8037+ nids = tls_mbedtls_append_curve(ids, nids, idsz, info->tls_id);
8038+ if (-1 == nids) return 0;
8039+ }
8040+
8041+ /* mod_openssl configures "prime256v1" if curve list not specified,
8042+ * but mbedtls provides a list of supported curves if not explicitly set */
8043+ if (-1 == nids) return 1; /* empty list; no-op */
8044+
8045+ ids[++nids] = 0; /* terminate list */
8046+ ++nids;
8047+
8048+ /* curves list must be persistent for lifetime of mbedtls_ssl_config */
8049+ tls_conf->curves = os_malloc(nids * sizeof(uint16_t));
8050+ if (tls_conf->curves == NULL)
8051+ return 0;
8052+ os_memcpy(tls_conf->curves, ids, nids * sizeof(uint16_t));
8053+
8054+ mbedtls_ssl_conf_groups(&tls_conf->conf, tls_conf->curves);
8055+ return 1;
8056+}
8057+#endif /* MBEDTLS_VERSION_NUMBER >= 0x03010000 */ /* mbedtls 3.1.0 */
8058+
8059+
8060+/* data copied from lighttpd src/mod_mbedtls.c (BSD-3-Clause) */
8061+static const int suite_AES_256_ephemeral[] = {
8062+ /* All AES-256 ephemeral suites */
8063+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
8064+ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
8065+ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
8066+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM,
8067+ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM,
8068+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
8069+ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
8070+ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
8071+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
8072+ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
8073+ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
8074+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8,
8075+ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8
8076+};
8077+
8078+/* data copied from lighttpd src/mod_mbedtls.c (BSD-3-Clause) */
8079+static const int suite_AES_128_ephemeral[] = {
8080+ /* All AES-128 ephemeral suites */
8081+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
8082+ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
8083+ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
8084+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM,
8085+ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM,
8086+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
8087+ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
8088+ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
8089+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
8090+ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
8091+ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
8092+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,
8093+ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8
8094+};
8095+
8096+/* data copied from lighttpd src/mod_mbedtls.c (BSD-3-Clause) */
8097+/* HIGH cipher list (mapped from openssl list to mbedtls) */
8098+static const int suite_HIGH[] = {
8099+ MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
8100+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
8101+ MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
8102+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
8103+ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
8104+ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
8105+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM,
8106+ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM,
8107+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
8108+ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
8109+ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
8110+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
8111+ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
8112+ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
8113+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8,
8114+ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8,
8115+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
8116+ MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,
8117+ MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
8118+ MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
8119+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384,
8120+ MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384,
8121+ MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384,
8122+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
8123+ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
8124+ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
8125+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM,
8126+ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM,
8127+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
8128+ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
8129+ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
8130+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
8131+ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
8132+ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
8133+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,
8134+ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8,
8135+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
8136+ MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
8137+ MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
8138+ MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
8139+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256,
8140+ MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256,
8141+ MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256,
8142+ MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
8143+ MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
8144+ MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,
8145+ MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM,
8146+ MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
8147+ MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,
8148+ MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA,
8149+ MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA,
8150+ MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
8151+ MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
8152+ MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8,
8153+ MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384,
8154+ MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256,
8155+ MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM,
8156+ MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
8157+ MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
8158+ MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
8159+ MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA,
8160+ MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
8161+ MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
8162+ MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8,
8163+ MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256,
8164+ MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384,
8165+ MBEDTLS_TLS_RSA_WITH_AES_256_CCM,
8166+ MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256,
8167+ MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA,
8168+ MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8,
8169+ MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,
8170+ MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,
8171+ MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384,
8172+ MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256,
8173+ MBEDTLS_TLS_RSA_WITH_AES_128_CCM,
8174+ MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256,
8175+ MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA,
8176+ MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8,
8177+ MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,
8178+ MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,
8179+ MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256,
8180+ MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256,
8181+ MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,
8182+ MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,
8183+ MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA,
8184+ MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384,
8185+ MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384,
8186+ MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256,
8187+ MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256,
8188+ MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA,
8189+ MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256,
8190+ MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256,
8191+ MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256,
8192+ MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384,
8193+ MBEDTLS_TLS_PSK_WITH_AES_256_CCM,
8194+ MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384,
8195+ MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA,
8196+ MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384,
8197+ MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8,
8198+ MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384,
8199+ MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256,
8200+ MBEDTLS_TLS_PSK_WITH_AES_128_CCM,
8201+ MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256,
8202+ MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA,
8203+ MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256,
8204+ MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8,
8205+ MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256
8206+};
8207+
8208+
8209+__attribute_noinline__
8210+static int
8211+tls_mbedtls_append_ciphersuite (int *ids, int nids, int idsz, const int *x, int xsz)
8212+{
8213+ if (xsz >= idsz - (nids + 1)) {
8214+ emsg(MSG_ERROR, "error: too many ciphers during list expand");
8215+ return -1;
8216+ }
8217+
8218+ for (int i = 0; i < xsz; ++i)
8219+ ids[++nids] = x[i];
8220+
8221+ return nids;
8222+}
8223+
8224+
8225+static int
8226+tls_mbedtls_translate_ciphername(int id, char *buf, size_t buflen)
8227+{
8228+ const mbedtls_ssl_ciphersuite_t *info =
8229+ mbedtls_ssl_ciphersuite_from_id(id);
8230+ if (info == NULL)
8231+ return 0;
8232+ const char *name = mbedtls_ssl_ciphersuite_get_name(info);
8233+ const size_t len = os_strlen(name);
8234+ if (len == 7 && 0 == os_memcmp(name, "unknown", 7))
8235+ return 0;
8236+ if (len >= buflen)
8237+ return 0;
8238+ os_strlcpy(buf, name, buflen);
8239+
8240+ /* attempt to translate mbedtls string to openssl string
8241+ * (some heuristics; incomplete) */
8242+ size_t i = 0, j = 0;
8243+ if (buf[0] == 'T') {
8244+ if (os_strncmp(buf, "TLS1-3-", 7) == 0) {
8245+ buf[3] = '-';
8246+ j = 4; /* remove "1-3" from "TLS1-3-" prefix */
8247+ i = 7;
8248+ }
8249+ else if (os_strncmp(buf, "TLS-", 4) == 0)
8250+ i = 4; /* remove "TLS-" prefix */
8251+ }
8252+ for (; buf[i]; ++i) {
8253+ if (buf[i] == '-') {
8254+ if (i >= 3) {
8255+ if (0 == os_memcmp(buf+i-3, "AES", 3))
8256+ continue; /* "AES-" -> "AES" */
8257+ }
8258+ if (i >= 4) {
8259+ if (0 == os_memcmp(buf+i-4, "WITH", 4)) {
8260+ j -= 4; /* remove "WITH-" */
8261+ continue;
8262+ }
8263+ }
8264+ }
8265+ buf[j++] = buf[i];
8266+ }
8267+ buf[j] = '\0';
8268+
8269+ return j;
8270+}
8271+
8272+
8273+__attribute_noinline__
8274+static int
8275+tls_mbedtls_set_ciphersuites(struct tls_conf *tls_conf, int *ids, int nids)
8276+{
8277+ /* ciphersuites list must be persistent for lifetime of mbedtls_ssl_config*/
8278+ os_free(tls_conf->ciphersuites);
8279+ tls_conf->ciphersuites = os_malloc(nids * sizeof(int));
8280+ if (tls_conf->ciphersuites == NULL)
8281+ return 0;
8282+ os_memcpy(tls_conf->ciphersuites, ids, nids * sizeof(int));
8283+ mbedtls_ssl_conf_ciphersuites(&tls_conf->conf, tls_conf->ciphersuites);
8284+ return 1;
8285+}
8286+
8287+
8288+static int
8289+tls_mbedtls_set_ciphers(struct tls_conf *tls_conf, const char *ciphers)
8290+{
8291+ char buf[64];
8292+ int ids[512];
8293+ int nids = -1;
8294+ const int idsz = (int)(sizeof(ids)/sizeof(*ids)-1);
8295+ const char *next;
8296+ size_t blen, clen;
8297+ do {
8298+ next = os_strchr(ciphers, ':');
8299+ clen = next ? (size_t)(next - ciphers) : os_strlen(ciphers);
8300+ if (!clen)
8301+ continue;
8302+
8303+ /* special-case a select set of openssl group names for hwsim tests */
8304+ /* (review; remove excess code if tests are not run for non-OpenSSL?) */
8305+ if (clen == 9 && os_memcmp(ciphers, "SUITEB192", 9) == 0) {
8306+ static int ssl_preset_suiteb192_ciphersuites[] = {
8307+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
8308+ 0
8309+ };
8310+ return tls_mbedtls_set_ciphersuites(tls_conf,
8311+ ssl_preset_suiteb192_ciphersuites,
8312+ 2);
8313+ }
8314+ if (clen == 9 && os_memcmp(ciphers, "SUITEB128", 9) == 0) {
8315+ static int ssl_preset_suiteb128_ciphersuites[] = {
8316+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
8317+ 0
8318+ };
8319+ return tls_mbedtls_set_ciphersuites(tls_conf,
8320+ ssl_preset_suiteb128_ciphersuites,
8321+ 2);
8322+ }
8323+ if (clen == 7 && os_memcmp(ciphers, "DEFAULT", 7) == 0)
8324+ continue;
8325+ if (clen == 6 && os_memcmp(ciphers, "AES128", 6) == 0) {
8326+ nids = tls_mbedtls_append_ciphersuite(ids, nids, idsz,
8327+ suite_AES_128_ephemeral,
8328+ (int)ARRAY_SIZE(suite_AES_128_ephemeral));
8329+ if (nids == -1)
8330+ return 0;
8331+ continue;
8332+ }
8333+ if (clen == 6 && os_memcmp(ciphers, "AES256", 6) == 0) {
8334+ nids = tls_mbedtls_append_ciphersuite(ids, nids, idsz,
8335+ suite_AES_256_ephemeral,
8336+ (int)ARRAY_SIZE(suite_AES_256_ephemeral));
8337+ if (nids == -1)
8338+ return 0;
8339+ continue;
8340+ }
8341+ if (clen == 4 && os_memcmp(ciphers, "HIGH", 4) == 0) {
8342+ nids = tls_mbedtls_append_ciphersuite(ids, nids, idsz, suite_HIGH,
8343+ (int)ARRAY_SIZE(suite_HIGH));
8344+ if (nids == -1)
8345+ return 0;
8346+ continue;
8347+ }
8348+ /* ignore anonymous cipher group names (?not supported by mbedtls?) */
8349+ if (clen == 4 && os_memcmp(ciphers, "!ADH", 4) == 0)
8350+ continue;
8351+ if (clen == 6 && os_memcmp(ciphers, "-aECDH", 6) == 0)
8352+ continue;
8353+ if (clen == 7 && os_memcmp(ciphers, "-aECDSA", 7) == 0)
8354+ continue;
8355+
8356+ /* attempt to match mbedtls cipher names
8357+ * nb: does not support openssl group names or list manipulation syntax
8358+ * (alt: could copy almost 1200 lines (!!!) of lighttpd mod_mbedtls.c
8359+ * mod_mbedtls_ssl_conf_ciphersuites() to translate strings)
8360+ * note: not efficient to rewrite list for each ciphers entry,
8361+ * but this code is expected to run only at startup
8362+ */
8363+ const int *list = mbedtls_ssl_list_ciphersuites();
8364+ for (; *list; ++list) {
8365+ blen = tls_mbedtls_translate_ciphername(*list,buf,sizeof(buf));
8366+ if (!blen)
8367+ continue;
8368+
8369+ /* matching heuristics additional to translate_ciphername above */
8370+ if (blen == clen+4) {
8371+ char *cbc = os_strstr(buf, "CBC-");
8372+ if (cbc) {
8373+ os_memmove(cbc, cbc+4, blen-(cbc+4-buf)+1); /*(w/ '\0')*/
8374+ blen -= 4;
8375+ }
8376+ }
8377+ if (blen >= clen && os_memcmp(ciphers, buf, clen) == 0
8378+ && (blen == clen
8379+ || (blen == clen+7 && os_memcmp(buf+clen, "-SHA256", 7)))) {
8380+ if (1 >= idsz - (nids + 1)) {
8381+ emsg(MSG_ERROR,
8382+ "error: too many ciphers during list expand");
8383+ return 0;
8384+ }
8385+ ids[++nids] = *list;
8386+ break;
8387+ }
8388+ }
8389+ if (*list == 0) {
8390+ wpa_printf(MSG_ERROR,
8391+ "MTLS: unrecognized cipher: %.*s", (int)clen, ciphers);
8392+ return 0;
8393+ }
8394+ } while ((ciphers = next ? next+1 : NULL));
8395+
8396+ if (-1 == nids) return 1; /* empty list; no-op */
8397+
8398+ ids[++nids] = 0; /* terminate list */
8399+ ++nids;
8400+
8401+ return tls_mbedtls_set_ciphersuites(tls_conf, ids, nids);
8402+}
8403+
8404+
8405+__attribute_noinline__
8406+static int tls_mbedtls_set_item(char **config_item, const char *item)
8407+{
8408+ os_free(*config_item);
8409+ *config_item = NULL;
8410+ return item ? (*config_item = os_strdup(item)) != NULL : 1;
8411+}
8412+
8413+
8414+static int tls_connection_set_subject_match(struct tls_conf *tls_conf,
8415+ const struct tls_connection_params *params)
8416+{
8417+ int rc = 1;
8418+ rc &= tls_mbedtls_set_item(&tls_conf->subject_match,
8419+ params->subject_match);
8420+ rc &= tls_mbedtls_set_item(&tls_conf->altsubject_match,
8421+ params->altsubject_match);
8422+ rc &= tls_mbedtls_set_item(&tls_conf->suffix_match,
8423+ params->suffix_match);
8424+ rc &= tls_mbedtls_set_item(&tls_conf->domain_match,
8425+ params->domain_match);
8426+ rc &= tls_mbedtls_set_item(&tls_conf->check_cert_subject,
8427+ params->check_cert_subject);
8428+ return rc;
8429+}
8430+
8431+
8432+/* duplicated in crypto_mbedtls.c:crypto_mbedtls_readfile()*/
8433+__attribute_noinline__
8434+static int tls_mbedtls_readfile(const char *path, u8 **buf, size_t *n)
8435+{
8436+ #if 0 /* #ifdef MBEDTLS_FS_IO */
8437+ /*(includes +1 for '\0' needed by mbedtls PEM parsing funcs)*/
8438+ if (mbedtls_pk_load_file(path, (unsigned char **)buf, n) != 0) {
8439+ wpa_printf(MSG_ERROR, "error: mbedtls_pk_load_file %s", path);
8440+ return -1;
8441+ }
8442+ #else
8443+ /*(use os_readfile() so that we can use os_free()
8444+ *(if we use mbedtls_pk_load_file() above, macros prevent calling free()
8445+ * directly #if defined(OS_REJECT_C_LIB_FUNCTIONS) and calling os_free()
8446+ * on buf aborts in tests if buf not allocated via os_malloc())*/
8447+ *buf = (u8 *)os_readfile(path, n);
8448+ if (!*buf) {
8449+ wpa_printf(MSG_ERROR, "error: os_readfile %s", path);
8450+ return -1;
8451+ }
8452+ u8 *buf0 = os_realloc(*buf, *n+1);
8453+ if (!buf0) {
8454+ bin_clear_free(*buf, *n);
8455+ *buf = NULL;
8456+ return -1;
8457+ }
8458+ buf0[(*n)++] = '\0';
8459+ *buf = buf0;
8460+ #endif
8461+ return 0;
8462+}
8463+
8464+
8465+static int tls_mbedtls_set_crl(struct tls_conf *tls_conf, const u8 *data, size_t len)
8466+{
8467+ /* do not use mbedtls_x509_crl_parse() on PEM unless it contains CRL */
8468+ if (len && data[len-1] == '\0'
8469+ && NULL == os_strstr((const char *)data,"-----BEGIN X509 CRL-----")
8470+ && tls_mbedtls_data_is_pem(data))
8471+ return 0;
8472+
8473+ mbedtls_x509_crl crl;
8474+ mbedtls_x509_crl_init(&crl);
8475+ int rc = mbedtls_x509_crl_parse(&crl, data, len);
8476+ if (rc < 0) {
8477+ mbedtls_x509_crl_free(&crl);
8478+ return rc == MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ? 0 : rc;
8479+ }
8480+
8481+ mbedtls_x509_crl *crl_new = os_malloc(sizeof(crl));
8482+ if (crl_new == NULL) {
8483+ mbedtls_x509_crl_free(&crl);
8484+ return MBEDTLS_ERR_X509_ALLOC_FAILED;
8485+ }
8486+ os_memcpy(crl_new, &crl, sizeof(crl));
8487+
8488+ mbedtls_x509_crl *crl_old = tls_conf->crl;
8489+ tls_conf->crl = crl_new;
8490+ if (crl_old) {
8491+ mbedtls_x509_crl_free(crl_old);
8492+ os_free(crl_old);
8493+ }
8494+ return 0;
8495+}
8496+
8497+
8498+static int tls_mbedtls_set_ca(struct tls_conf *tls_conf, u8 *data, size_t len)
8499+{
8500+ /* load crt struct onto stack and then copy into tls_conf in
8501+ * order to preserve existing tls_conf value if error occurs
8502+ *
8503+ * hostapd is not threaded, or else should allocate memory and swap in
8504+ * pointer reduce race condition. (If threaded, would also need to
8505+ * keep reference count of use to avoid freeing while still in use.) */
8506+
8507+ mbedtls_x509_crt crt;
8508+ mbedtls_x509_crt_init(&crt);
8509+ int rc = mbedtls_x509_crt_parse(&crt, data, len);
8510+ if (rc < 0) {
8511+ mbedtls_x509_crt_free(&crt);
8512+ return rc;
8513+ }
8514+
8515+ mbedtls_x509_crt_free(&tls_conf->ca_cert);
8516+ os_memcpy(&tls_conf->ca_cert, &crt, sizeof(crt));
8517+ return 0;
8518+}
8519+
8520+
8521+static int tls_mbedtls_set_ca_and_crl(struct tls_conf *tls_conf, const char *ca_cert_file)
8522+{
8523+ size_t len;
8524+ u8 *data;
8525+ if (tls_mbedtls_readfile(ca_cert_file, &data, &len))
8526+ return -1;
8527+
8528+ int rc;
8529+ if (0 == (rc = tls_mbedtls_set_ca(tls_conf, data, len))
8530+ && (!tls_mbedtls_data_is_pem(data) /*skip parse for CRL if not PEM*/
8531+ || 0 == (rc = tls_mbedtls_set_crl(tls_conf, data, len)))) {
8532+ mbedtls_ssl_conf_ca_chain(&tls_conf->conf,
8533+ &tls_conf->ca_cert,
8534+ tls_conf->crl);
8535+ }
8536+ else {
8537+ elog(rc, __func__);
8538+ emsg(MSG_ERROR, ca_cert_file);
8539+ }
8540+
8541+ forced_memzero(data, len);
8542+ os_free(data);
8543+ return rc;
8544+}
8545+
8546+
8547+static void tls_mbedtls_refresh_crl(void)
8548+{
8549+ /* check for CRL refresh
8550+ * continue even if error occurs; continue with previous cert, CRL */
8551+ unsigned int crl_reload_interval = tls_ctx_global.crl_reload_interval;
8552+ const char *ca_cert_file = tls_ctx_global.ca_cert_file;
8553+ if (!crl_reload_interval || !ca_cert_file)
8554+ return;
8555+
8556+ struct os_reltime *previous = &tls_ctx_global.crl_reload_previous;
8557+ struct os_reltime now;
8558+ if (os_get_reltime(&now) != 0
8559+ || !os_reltime_expired(&now, previous, crl_reload_interval))
8560+ return;
8561+
8562+ /* Note: modifying global state is not thread-safe
8563+ * if in use by existing connections
8564+ *
8565+ * src/utils/os.h does not provide a portable stat()
8566+ * or else it would be a good idea to check mtime and size,
8567+ * and avoid reloading if file has not changed */
8568+
8569+ if (tls_mbedtls_set_ca_and_crl(tls_ctx_global.tls_conf, ca_cert_file) == 0)
8570+ *previous = now;
8571+}
8572+
8573+
8574+static int tls_mbedtls_set_ca_cert(struct tls_conf *tls_conf,
8575+ const struct tls_connection_params *params)
8576+{
8577+ if (params->ca_cert) {
8578+ if (os_strncmp(params->ca_cert, "probe://", 8) == 0) {
8579+ tls_conf->ca_cert_probe = 1;
8580+ tls_conf->has_ca_cert = 1;
8581+ return 0;
8582+ }
8583+
8584+ if (os_strncmp(params->ca_cert, "hash://", 7) == 0) {
8585+ const char *pos = params->ca_cert + 7;
8586+ if (os_strncmp(pos, "server/sha256/", 14) != 0) {
8587+ emsg(MSG_ERROR, "unsupported ca_cert hash value");
8588+ return -1;
8589+ }
8590+ pos += 14;
8591+ if (os_strlen(pos) != SHA256_DIGEST_LENGTH*2) {
8592+ emsg(MSG_ERROR, "unexpected ca_cert hash length");
8593+ return -1;
8594+ }
8595+ if (hexstr2bin(pos, tls_conf->ca_cert_hash,
8596+ SHA256_DIGEST_LENGTH) < 0) {
8597+ emsg(MSG_ERROR, "invalid ca_cert hash value");
8598+ return -1;
8599+ }
8600+ emsg(MSG_DEBUG, "checking only server certificate match");
8601+ tls_conf->verify_depth0_only = 1;
8602+ tls_conf->has_ca_cert = 1;
8603+ return 0;
8604+ }
8605+
8606+ if (tls_mbedtls_set_ca_and_crl(tls_conf, params->ca_cert) != 0)
8607+ return -1;
8608+ }
8609+ if (params->ca_cert_blob) {
8610+ size_t len = params->ca_cert_blob_len;
8611+ int is_pem = tls_mbedtls_data_is_pem(params->ca_cert_blob);
8612+ if (len && params->ca_cert_blob[len-1] != '\0' && is_pem)
8613+ ++len; /*(include '\0' in len for PEM)*/
8614+ int ret = mbedtls_x509_crt_parse(&tls_conf->ca_cert,
8615+ params->ca_cert_blob, len);
8616+ if (ret != 0) {
8617+ elog(ret, "mbedtls_x509_crt_parse");
8618+ return -1;
8619+ }
8620+ if (is_pem) { /*(ca_cert_blob in DER format contains ca cert only)*/
8621+ ret = tls_mbedtls_set_crl(tls_conf, params->ca_cert_blob, len);
8622+ if (ret != 0) {
8623+ elog(ret, "mbedtls_x509_crl_parse");
8624+ return -1;
8625+ }
8626+ }
8627+ }
8628+
8629+ if (mbedtls_x509_time_is_future(&tls_conf->ca_cert.valid_from)
8630+ || mbedtls_x509_time_is_past(&tls_conf->ca_cert.valid_to)) {
8631+ emsg(MSG_WARNING, "ca_cert expired or not yet valid");
8632+ if (params->ca_cert)
8633+ emsg(MSG_WARNING, params->ca_cert);
8634+ }
8635+
8636+ tls_conf->has_ca_cert = 1;
8637+ return 0;
8638+}
8639+
8640+
8641+static int tls_mbedtls_set_certs(struct tls_conf *tls_conf,
8642+ const struct tls_connection_params *params)
8643+{
8644+ int ret;
8645+
8646+ if (params->ca_cert || params->ca_cert_blob) {
8647+ if (tls_mbedtls_set_ca_cert(tls_conf, params) != 0)
8648+ return -1;
8649+ }
8650+ else if (params->ca_path) {
8651+ emsg(MSG_INFO, "ca_path support not implemented");
8652+ return -1;
8653+ }
8654+
8655+ if (!tls_conf->has_ca_cert)
8656+ mbedtls_ssl_conf_authmode(&tls_conf->conf, MBEDTLS_SSL_VERIFY_NONE);
8657+ else {
8658+ /* Initial setting: REQUIRED for client, OPTIONAL for server
8659+ * (see also tls_connection_set_verify()) */
8660+ tls_conf->verify_peer = (tls_ctx_global.tls_conf == NULL);
8661+ int authmode = tls_conf->verify_peer
8662+ ? MBEDTLS_SSL_VERIFY_REQUIRED
8663+ : MBEDTLS_SSL_VERIFY_OPTIONAL;
8664+ mbedtls_ssl_conf_authmode(&tls_conf->conf, authmode);
8665+ mbedtls_ssl_conf_ca_chain(&tls_conf->conf,
8666+ &tls_conf->ca_cert,
8667+ tls_conf->crl);
8668+
8669+ if (!tls_connection_set_subject_match(tls_conf, params))
8670+ return -1;
8671+ }
8672+
8673+ if (params->client_cert2) /*(yes, server_cert2 in msg below)*/
8674+ emsg(MSG_INFO, "server_cert2 support not implemented");
8675+
8676+ if (params->client_cert) {
8677+ size_t len;
8678+ u8 *data;
8679+ if (tls_mbedtls_readfile(params->client_cert, &data, &len))
8680+ return -1;
8681+ ret = mbedtls_x509_crt_parse(&tls_conf->client_cert, data, len);
8682+ forced_memzero(data, len);
8683+ os_free(data);
8684+ }
8685+ if (params->client_cert_blob) {
8686+ size_t len = params->client_cert_blob_len;
8687+ if (len && params->client_cert_blob[len-1] != '\0'
8688+ && tls_mbedtls_data_is_pem(params->client_cert_blob))
8689+ ++len; /*(include '\0' in len for PEM)*/
8690+ ret = mbedtls_x509_crt_parse(&tls_conf->client_cert,
8691+ params->client_cert_blob, len);
8692+ }
8693+ if (params->client_cert || params->client_cert_blob) {
8694+ if (ret < 0) {
8695+ elog(ret, "mbedtls_x509_crt_parse");
8696+ if (params->client_cert)
8697+ emsg(MSG_ERROR, params->client_cert);
8698+ return -1;
8699+ }
8700+ if (mbedtls_x509_time_is_future(&tls_conf->client_cert.valid_from)
8701+ || mbedtls_x509_time_is_past(&tls_conf->client_cert.valid_to)) {
8702+ emsg(MSG_WARNING, "cert expired or not yet valid");
8703+ if (params->client_cert)
8704+ emsg(MSG_WARNING, params->client_cert);
8705+ }
8706+ tls_conf->has_client_cert = 1;
8707+ }
8708+
8709+ if (params->private_key || params->private_key_blob) {
8710+ size_t len = params->private_key_blob_len;
8711+ u8 *data;
8712+ *(const u8 **)&data = params->private_key_blob;
8713+ if (len && data[len-1] != '\0' && tls_mbedtls_data_is_pem(data))
8714+ ++len; /*(include '\0' in len for PEM)*/
8715+ if (params->private_key
8716+ && tls_mbedtls_readfile(params->private_key, &data, &len)) {
8717+ return -1;
8718+ }
8719+ const char *pwd = params->private_key_passwd;
8720+ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
8721+ ret = mbedtls_pk_parse_key(&tls_conf->private_key,
8722+ data, len,
8723+ (const unsigned char *)pwd,
8724+ pwd ? os_strlen(pwd) : 0,
8725+ mbedtls_ctr_drbg_random,
8726+ tls_ctx_global.ctr_drbg);
8727+ #else
8728+ ret = mbedtls_pk_parse_key(&tls_conf->private_key,
8729+ data, len,
8730+ (const unsigned char *)pwd,
8731+ pwd ? os_strlen(pwd) : 0);
8732+ #endif
8733+ if (params->private_key) {
8734+ forced_memzero(data, len);
8735+ os_free(data);
8736+ }
8737+ if (ret < 0) {
8738+ elog(ret, "mbedtls_pk_parse_key");
8739+ return -1;
8740+ }
8741+ tls_conf->has_private_key = 1;
8742+ }
8743+
8744+ if (tls_conf->has_client_cert && tls_conf->has_private_key) {
8745+ ret = mbedtls_ssl_conf_own_cert(
8746+ &tls_conf->conf, &tls_conf->client_cert, &tls_conf->private_key);
8747+ if (ret < 0) {
8748+ elog(ret, "mbedtls_ssl_conf_own_cert");
8749+ return -1;
8750+ }
8751+ }
8752+
8753+ return 0;
8754+}
8755+
8756+
8757+/* mbedtls_x509_crt_profile_suiteb plus rsa_min_bitlen 2048 */
8758+/* (reference: see also mbedtls_x509_crt_profile_next) */
8759+/* ??? should permit SHA-512, too, and additional curves ??? */
8760+static const mbedtls_x509_crt_profile tls_mbedtls_crt_profile_suiteb128 =
8761+{
8762+ /* Only SHA-256 and 384 */
8763+ MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
8764+ MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ),
8765+ /* Only ECDSA */
8766+ MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ) |
8767+ MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECKEY ),
8768+#if defined(MBEDTLS_ECP_C)
8769+ /* Only NIST P-256 and P-384 */
8770+ MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) |
8771+ MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ),
8772+#else
8773+ 0,
8774+#endif
8775+ 2048,
8776+};
8777+
8778+
8779+/* stricter than mbedtls_x509_crt_profile_suiteb */
8780+/* (reference: see also mbedtls_x509_crt_profile_next) */
8781+/* ??? should permit SHA-512, too, and additional curves ??? */
8782+static const mbedtls_x509_crt_profile tls_mbedtls_crt_profile_suiteb192 =
8783+{
8784+ /* Only SHA-384 */
8785+ MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ),
8786+ /* Only ECDSA */
8787+ MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ) |
8788+ MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECKEY ),
8789+#if defined(MBEDTLS_ECP_C)
8790+ /* Only NIST P-384 */
8791+ MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ),
8792+#else
8793+ 0,
8794+#endif
8795+ 3072,
8796+};
8797+
8798+
8799+/* stricter than mbedtls_x509_crt_profile_suiteb except allow any PK alg */
8800+/* (reference: see also mbedtls_x509_crt_profile_next) */
8801+/* ??? should permit SHA-512, too, and additional curves ??? */
8802+static const mbedtls_x509_crt_profile tls_mbedtls_crt_profile_suiteb192_anypk =
8803+{
8804+ /* Only SHA-384 */
8805+ MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ),
8806+ 0xFFFFFFF, /* Any PK alg */
8807+#if defined(MBEDTLS_ECP_C)
8808+ /* Only NIST P-384 */
8809+ MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ),
8810+#else
8811+ 0,
8812+#endif
8813+ 3072,
8814+};
8815+
8816+
8817+static int tls_mbedtls_set_params(struct tls_conf *tls_conf,
8818+ const struct tls_connection_params *params)
8819+{
8820+ tls_conf->flags = params->flags;
8821+
8822+ if (tls_conf->flags & TLS_CONN_REQUIRE_OCSP_ALL) {
8823+ emsg(MSG_INFO, "ocsp=3 not supported");
8824+ return -1;
8825+ }
8826+
8827+ if (tls_conf->flags & TLS_CONN_REQUIRE_OCSP) {
8828+ emsg(MSG_INFO, "ocsp not supported");
8829+ return -1;
8830+ }
8831+
8832+ int suiteb128 = 0;
8833+ int suiteb192 = 0;
8834+ if (params->openssl_ciphers) {
8835+ if (os_strcmp(params->openssl_ciphers, "SUITEB192") == 0) {
8836+ suiteb192 = 1;
8837+ tls_conf->flags |= TLS_CONN_SUITEB;
8838+ }
8839+ if (os_strcmp(params->openssl_ciphers, "SUITEB128") == 0) {
8840+ suiteb128 = 1;
8841+ tls_conf->flags |= TLS_CONN_SUITEB;
8842+ }
8843+ }
8844+
8845+ int ret = mbedtls_ssl_config_defaults(
8846+ &tls_conf->conf, tls_ctx_global.tls_conf ? MBEDTLS_SSL_IS_SERVER
8847+ : MBEDTLS_SSL_IS_CLIENT,
8848+ MBEDTLS_SSL_TRANSPORT_STREAM,
8849+ (tls_conf->flags & TLS_CONN_SUITEB) ? MBEDTLS_SSL_PRESET_SUITEB
8850+ : MBEDTLS_SSL_PRESET_DEFAULT);
8851+ if (ret != 0) {
8852+ elog(ret, "mbedtls_ssl_config_defaults");
8853+ return -1;
8854+ }
8855+
8856+ if (suiteb128) {
8857+ mbedtls_ssl_conf_cert_profile(&tls_conf->conf,
8858+ &tls_mbedtls_crt_profile_suiteb128);
8859+ mbedtls_ssl_conf_dhm_min_bitlen(&tls_conf->conf, 2048);
8860+ }
8861+ else if (suiteb192) {
8862+ mbedtls_ssl_conf_cert_profile(&tls_conf->conf,
8863+ &tls_mbedtls_crt_profile_suiteb192);
8864+ mbedtls_ssl_conf_dhm_min_bitlen(&tls_conf->conf, 3072);
8865+ }
8866+ else if (tls_conf->flags & TLS_CONN_SUITEB) {
8867+ /* treat as suiteb192 while allowing any PK algorithm */
8868+ mbedtls_ssl_conf_cert_profile(&tls_conf->conf,
8869+ &tls_mbedtls_crt_profile_suiteb192_anypk);
8870+ mbedtls_ssl_conf_dhm_min_bitlen(&tls_conf->conf, 3072);
8871+ }
8872+
8873+ tls_mbedtls_set_allowed_tls_vers(tls_conf, &tls_conf->conf);
8874+ ret = tls_mbedtls_set_certs(tls_conf, params);
8875+ if (ret != 0)
8876+ return -1;
8877+
8878+ if (params->dh_file
8879+ && !tls_mbedtls_set_dhparams(tls_conf, params->dh_file)) {
8880+ return -1;
8881+ }
8882+
8883+ if (params->openssl_ecdh_curves
8884+ && !tls_mbedtls_set_curves(tls_conf, params->openssl_ecdh_curves)) {
8885+ return -1;
8886+ }
8887+
8888+ if (params->openssl_ciphers) {
8889+ if (!tls_mbedtls_set_ciphers(tls_conf, params->openssl_ciphers))
8890+ return -1;
8891+ }
8892+ else if (tls_conf->flags & TLS_CONN_SUITEB) {
8893+ /* special-case a select set of ciphers for hwsim tests */
8894+ if (!tls_mbedtls_set_ciphers(tls_conf,
8895+ (tls_conf->flags & TLS_CONN_SUITEB_NO_ECDH)
8896+ ? "DHE-RSA-AES256-GCM-SHA384"
8897+ : "ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384"))
8898+ return -1;
8899+ }
8900+
8901+ return 0;
8902+}
8903+
8904+
8905+int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
8906+ const struct tls_connection_params *params)
8907+{
8908+ if (conn == NULL || params == NULL)
8909+ return -1;
8910+
8911+ tls_conf_deinit(conn->tls_conf);
8912+ struct tls_conf *tls_conf = conn->tls_conf = tls_conf_init(tls_ctx);
8913+ if (tls_conf == NULL)
8914+ return -1;
8915+
8916+ if (tls_ctx_global.tls_conf) {
8917+ tls_conf->check_crl = tls_ctx_global.tls_conf->check_crl;
8918+ tls_conf->check_crl_strict = tls_ctx_global.tls_conf->check_crl_strict;
8919+ /*(tls_openssl.c inherits check_cert_subject from global conf)*/
8920+ if (tls_ctx_global.tls_conf->check_cert_subject) {
8921+ tls_conf->check_cert_subject =
8922+ os_strdup(tls_ctx_global.tls_conf->check_cert_subject);
8923+ if (tls_conf->check_cert_subject == NULL)
8924+ return -1;
8925+ }
8926+ }
8927+
8928+ if (tls_mbedtls_set_params(tls_conf, params) != 0)
8929+ return -1;
8930+ conn->verify_peer = tls_conf->verify_peer;
8931+
8932+ return tls_mbedtls_ssl_setup(conn);
8933+}
8934+
8935+
8936+#ifdef TLS_MBEDTLS_SESSION_TICKETS
8937+
8938+static int tls_mbedtls_clienthello_session_ticket_prep (struct tls_connection *conn,
8939+ const u8 *data, size_t len)
8940+{
8941+ if (conn->tls_conf->flags & TLS_CONN_DISABLE_SESSION_TICKET)
8942+ return -1;
8943+ if (conn->clienthello_session_ticket)
8944+ tls_connection_deinit_clienthello_session_ticket(conn);
8945+ if (len) {
8946+ conn->clienthello_session_ticket = mbedtls_calloc(1, len);
8947+ if (conn->clienthello_session_ticket == NULL)
8948+ return -1;
8949+ conn->clienthello_session_ticket_len = len;
8950+ os_memcpy(conn->clienthello_session_ticket, data, len);
8951+ }
8952+ return 0;
8953+}
8954+
8955+
8956+static void tls_mbedtls_clienthello_session_ticket_set (struct tls_connection *conn)
8957+{
8958+ mbedtls_ssl_session *sess = conn->ssl.MBEDTLS_PRIVATE(session_negotiate);
8959+ if (sess->MBEDTLS_PRIVATE(ticket)) {
8960+ mbedtls_platform_zeroize(sess->MBEDTLS_PRIVATE(ticket),
8961+ sess->MBEDTLS_PRIVATE(ticket_len));
8962+ mbedtls_free(sess->MBEDTLS_PRIVATE(ticket));
8963+ }
8964+ sess->MBEDTLS_PRIVATE(ticket) = conn->clienthello_session_ticket;
8965+ sess->MBEDTLS_PRIVATE(ticket_len) = conn->clienthello_session_ticket_len;
8966+ sess->MBEDTLS_PRIVATE(ticket_lifetime) = 86400;/* XXX: can hint be 0? */
8967+
8968+ conn->clienthello_session_ticket = NULL;
8969+ conn->clienthello_session_ticket_len = 0;
8970+}
8971+
8972+
8973+static int tls_mbedtls_ssl_ticket_write(void *p_ticket,
8974+ const mbedtls_ssl_session *session,
8975+ unsigned char *start,
8976+ const unsigned char *end,
8977+ size_t *tlen,
8978+ uint32_t *lifetime)
8979+{
8980+ struct tls_connection *conn = p_ticket;
8981+ if (conn && conn->session_ticket_cb) {
8982+ /* see tls_mbedtls_clienthello_session_ticket_prep() */
8983+ /* see tls_mbedtls_clienthello_session_ticket_set() */
8984+ return 0;
8985+ }
8986+
8987+ return mbedtls_ssl_ticket_write(&tls_ctx_global.ticket_ctx,
8988+ session, start, end, tlen, lifetime);
8989+}
8990+
8991+
8992+static int tls_mbedtls_ssl_ticket_parse(void *p_ticket,
8993+ mbedtls_ssl_session *session,
8994+ unsigned char *buf,
8995+ size_t len)
8996+{
8997+ /* XXX: TODO: not implemented in client;
8998+ * mbedtls_ssl_conf_session_tickets_cb() callbacks only for TLS server*/
8999+
9000+ if (len == 0)
9001+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
9002+
9003+ struct tls_connection *conn = p_ticket;
9004+ if (conn && conn->session_ticket_cb) {
9005+ /* XXX: have random and secret been initialized yet?
9006+ * or must keys first be exported?
9007+ * EAP-FAST uses all args, EAP-TEAP only uses secret */
9008+ struct tls_random data;
9009+ if (tls_connection_get_random(NULL, conn, &data) != 0)
9010+ return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
9011+ int ret =
9012+ conn->session_ticket_cb(conn->session_ticket_cb_ctx,
9013+ buf, len,
9014+ data.client_random,
9015+ data.server_random,
9016+ conn->expkey_secret);
9017+ if (ret == 1) {
9018+ conn->resumed = 1;
9019+ return 0;
9020+ }
9021+ emsg(MSG_ERROR, "EAP session ticket ext not implemented");
9022+ return MBEDTLS_ERR_SSL_INVALID_MAC;
9023+ /*(non-zero return used for mbedtls debug logging)*/
9024+ }
9025+
9026+ /* XXX: TODO always use tls_mbedtls_ssl_ticket_parse() for callback? */
9027+ int rc = mbedtls_ssl_ticket_parse(&tls_ctx_global.ticket_ctx,
9028+ session, buf, len);
9029+ if (conn)
9030+ conn->resumed = (rc == 0);
9031+ return rc;
9032+}
9033+
9034+#endif /* TLS_MBEDTLS_SESSION_TICKETS */
9035+
9036+
9037+__attribute_cold__
9038+int tls_global_set_params(void *tls_ctx,
9039+ const struct tls_connection_params *params)
9040+{
9041+ /* XXX: why might global_set_params be called more than once? */
9042+ if (tls_ctx_global.tls_conf)
9043+ tls_conf_deinit(tls_ctx_global.tls_conf);
9044+ tls_ctx_global.tls_conf = tls_conf_init(tls_ctx);
9045+ if (tls_ctx_global.tls_conf == NULL)
9046+ return -1;
9047+
9048+ #ifdef MBEDTLS_SSL_SESSION_TICKETS
9049+ #ifdef MBEDTLS_SSL_TICKET_C
9050+ if (!(params->flags & TLS_CONN_DISABLE_SESSION_TICKET))
9051+ #ifdef TLS_MBEDTLS_SESSION_TICKETS
9052+ mbedtls_ssl_conf_session_tickets_cb(&tls_ctx_global.tls_conf->conf,
9053+ tls_mbedtls_ssl_ticket_write,
9054+ tls_mbedtls_ssl_ticket_parse,
9055+ NULL);
9056+ #else
9057+ mbedtls_ssl_conf_session_tickets_cb(&tls_ctx_global.tls_conf->conf,
9058+ mbedtls_ssl_ticket_write,
9059+ mbedtls_ssl_ticket_parse,
9060+ &tls_ctx_global.ticket_ctx);
9061+ #endif
9062+ #endif
9063+ #endif
9064+
9065+ os_free(tls_ctx_global.ocsp_stapling_response);
9066+ tls_ctx_global.ocsp_stapling_response = NULL;
9067+ if (params->ocsp_stapling_response)
9068+ tls_ctx_global.ocsp_stapling_response =
9069+ os_strdup(params->ocsp_stapling_response);
9070+
9071+ os_free(tls_ctx_global.ca_cert_file);
9072+ tls_ctx_global.ca_cert_file = NULL;
9073+ if (params->ca_cert)
9074+ tls_ctx_global.ca_cert_file = os_strdup(params->ca_cert);
9075+ return tls_mbedtls_set_params(tls_ctx_global.tls_conf, params);
9076+}
9077+
9078+
9079+int tls_global_set_verify(void *tls_ctx, int check_crl, int strict)
9080+{
9081+ tls_ctx_global.tls_conf->check_crl = check_crl;
9082+ tls_ctx_global.tls_conf->check_crl_strict = strict; /*(time checks)*/
9083+ return 0;
9084+}
9085+
9086+
9087+int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn,
9088+ int verify_peer, unsigned int flags,
9089+ const u8 *session_ctx, size_t session_ctx_len)
9090+{
9091+ /*(EAP server-side calls this from eap_server_tls_ssl_init())*/
9092+ if (conn == NULL)
9093+ return -1;
9094+
9095+ conn->tls_conf->flags |= flags;/* TODO: reprocess flags, if necessary */
9096+
9097+ int authmode;
9098+ switch (verify_peer) {
9099+ case 2: authmode = MBEDTLS_SSL_VERIFY_OPTIONAL; break;/*(eap_teap_init())*/
9100+ case 1: authmode = MBEDTLS_SSL_VERIFY_REQUIRED; break;
9101+ default: authmode = MBEDTLS_SSL_VERIFY_NONE; break;
9102+ }
9103+ mbedtls_ssl_set_hs_authmode(&conn->ssl, authmode);
9104+
9105+ if ((conn->verify_peer = (authmode != MBEDTLS_SSL_VERIFY_NONE)))
9106+ mbedtls_ssl_set_verify(&conn->ssl, tls_mbedtls_verify_cb, conn);
9107+ else
9108+ mbedtls_ssl_set_verify(&conn->ssl, NULL, NULL);
9109+
9110+ return 0;
9111+}
9112+
9113+
9114+#if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
9115+static void tls_connection_export_keys_cb(
9116+ void *p_expkey, mbedtls_ssl_key_export_type secret_type,
9117+ const unsigned char *secret, size_t secret_len,
9118+ const unsigned char client_random[MBEDTLS_EXPKEY_RAND_LEN],
9119+ const unsigned char server_random[MBEDTLS_EXPKEY_RAND_LEN],
9120+ mbedtls_tls_prf_types tls_prf_type)
9121+{
9122+ struct tls_connection *conn = p_expkey;
9123+ conn->tls_prf_type = tls_prf_type;
9124+ if (!tls_prf_type)
9125+ return;
9126+ if (secret_len > sizeof(conn->expkey_secret)) {
9127+ emsg(MSG_ERROR, "tls_connection_export_keys_cb secret too long");
9128+ conn->tls_prf_type = MBEDTLS_SSL_TLS_PRF_NONE; /* 0 */
9129+ return;
9130+ }
9131+ conn->expkey_secret_len = secret_len;
9132+ os_memcpy(conn->expkey_secret, secret, secret_len);
9133+ os_memcpy(conn->expkey_randbytes,
9134+ client_random, MBEDTLS_EXPKEY_RAND_LEN);
9135+ os_memcpy(conn->expkey_randbytes + MBEDTLS_EXPKEY_RAND_LEN,
9136+ server_random, MBEDTLS_EXPKEY_RAND_LEN);
9137+}
9138+#elif MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */
9139+static int tls_connection_export_keys_cb(
9140+ void *p_expkey,
9141+ const unsigned char *ms,
9142+ const unsigned char *kb,
9143+ size_t maclen,
9144+ size_t keylen,
9145+ size_t ivlen,
9146+ const unsigned char client_random[MBEDTLS_EXPKEY_RAND_LEN],
9147+ const unsigned char server_random[MBEDTLS_EXPKEY_RAND_LEN],
9148+ mbedtls_tls_prf_types tls_prf_type )
9149+{
9150+ struct tls_connection *conn = p_expkey;
9151+ conn->tls_prf_type = tls_prf_type;
9152+ if (!tls_prf_type)
9153+ return -1; /*(return value ignored by mbedtls)*/
9154+ conn->expkey_keyblock_size = maclen + keylen + ivlen;
9155+ conn->expkey_secret_len = MBEDTLS_EXPKEY_FIXED_SECRET_LEN;
9156+ os_memcpy(conn->expkey_secret, ms, MBEDTLS_EXPKEY_FIXED_SECRET_LEN);
9157+ os_memcpy(conn->expkey_randbytes,
9158+ client_random, MBEDTLS_EXPKEY_RAND_LEN);
9159+ os_memcpy(conn->expkey_randbytes + MBEDTLS_EXPKEY_RAND_LEN,
9160+ server_random, MBEDTLS_EXPKEY_RAND_LEN);
9161+ return 0;
9162+}
9163+#endif
9164+
9165+
9166+int tls_connection_get_random(void *tls_ctx, struct tls_connection *conn,
9167+ struct tls_random *data)
9168+{
9169+ if (!conn || !conn->tls_prf_type)
9170+ return -1;
9171+ data->client_random = conn->expkey_randbytes;
9172+ data->client_random_len = MBEDTLS_EXPKEY_RAND_LEN;
9173+ data->server_random = conn->expkey_randbytes + MBEDTLS_EXPKEY_RAND_LEN;
9174+ data->server_random_len = MBEDTLS_EXPKEY_RAND_LEN;
9175+ return 0;
9176+}
9177+
9178+
9179+int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
9180+ const char *label, const u8 *context,
9181+ size_t context_len, u8 *out, size_t out_len)
9182+{
9183+ /* (EAP-PEAP EAP-TLS EAP-TTLS) */
9184+ #if MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */
9185+ return (conn && conn->established && conn->tls_prf_type)
9186+ ? mbedtls_ssl_tls_prf(conn->tls_prf_type,
9187+ conn->expkey_secret, conn->expkey_secret_len, label,
9188+ conn->expkey_randbytes,
9189+ sizeof(conn->expkey_randbytes), out, out_len)
9190+ : -1;
9191+ #else
9192+ /* not implemented here for mbedtls < 2.18.0 */
9193+ return -1;
9194+ #endif
9195+}
9196+
9197+
9198+#ifdef TLS_MBEDTLS_EAP_FAST
9199+
9200+#if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
9201+/* keyblock size info is not exposed in mbed TLS 3.0.0 */
9202+/* extracted from mbedtls library/ssl_tls.c:ssl_tls12_populate_transform() */
9203+#include <mbedtls/ssl_ciphersuites.h>
9204+#include <mbedtls/cipher.h>
9205+static size_t tls_mbedtls_ssl_keyblock_size (mbedtls_ssl_context *ssl)
9206+{
9207+ #if !defined(MBEDTLS_USE_PSA_CRYPTO) /* XXX: (not extracted for PSA crypto) */
9208+ #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
9209+ if (tls_version == MBEDTLS_SSL_VERSION_TLS1_3)
9210+ return 0; /* (calculation not extracted) */
9211+ #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
9212+
9213+ int ciphersuite = mbedtls_ssl_get_ciphersuite_id_from_ssl(ssl);
9214+ const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
9215+ mbedtls_ssl_ciphersuite_from_id(ciphersuite);
9216+ if (ciphersuite_info == NULL)
9217+ return 0;
9218+
9219+ const mbedtls_cipher_info_t *cipher_info =
9220+ mbedtls_cipher_info_from_type(ciphersuite_info->MBEDTLS_PRIVATE(cipher));
9221+ if (cipher_info == NULL)
9222+ return 0;
9223+
9224+ #if MBEDTLS_VERSION_NUMBER >= 0x03010000 /* mbedtls 3.1.0 */
9225+ size_t keylen = mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8;
9226+ mbedtls_cipher_mode_t mode = mbedtls_cipher_info_get_mode(cipher_info);
9227+ #else
9228+ size_t keylen = cipher_info->MBEDTLS_PRIVATE(key_bitlen) / 8;
9229+ mbedtls_cipher_mode_t mode = cipher_info->MBEDTLS_PRIVATE(mode);
9230+ #endif
9231+ #if defined(MBEDTLS_GCM_C) || \
9232+ defined(MBEDTLS_CCM_C) || \
9233+ defined(MBEDTLS_CHACHAPOLY_C)
9234+ if (mode == MBEDTLS_MODE_GCM || mode == MBEDTLS_MODE_CCM)
9235+ return keylen + 4;
9236+ else if (mode == MBEDTLS_MODE_CHACHAPOLY)
9237+ return keylen + 12;
9238+ else
9239+ #endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */
9240+ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
9241+ {
9242+ const mbedtls_md_info_t *md_info =
9243+ mbedtls_md_info_from_type(ciphersuite_info->MBEDTLS_PRIVATE(mac));
9244+ if (md_info == NULL)
9245+ return 0;
9246+ size_t mac_key_len = mbedtls_md_get_size(md_info);
9247+ size_t ivlen = mbedtls_cipher_info_get_iv_size(cipher_info);
9248+ return keylen + mac_key_len + ivlen;
9249+ }
9250+ #endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
9251+ #endif /* !MBEDTLS_USE_PSA_CRYPTO *//* (not extracted for PSA crypto) */
9252+ return 0;
9253+}
9254+#endif /* MBEDTLS_VERSION_NUMBER >= 0x03000000 *//* mbedtls 3.0.0 */
9255+
9256+
9257+int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn,
9258+ u8 *out, size_t out_len)
9259+{
9260+ /* XXX: has export keys callback been run? */
9261+ if (!conn || !conn->tls_prf_type)
9262+ return -1;
9263+
9264+ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
9265+ conn->expkey_keyblock_size = tls_mbedtls_ssl_keyblock_size(&conn->ssl);
9266+ if (conn->expkey_keyblock_size == 0)
9267+ return -1;
9268+ #endif
9269+ size_t skip = conn->expkey_keyblock_size * 2;
9270+ unsigned char *tmp_out = os_malloc(skip + out_len);
9271+ if (!tmp_out)
9272+ return -1;
9273+
9274+ /* server_random and then client_random */
9275+ unsigned char seed[MBEDTLS_EXPKEY_RAND_LEN*2];
9276+ os_memcpy(seed, conn->expkey_randbytes + MBEDTLS_EXPKEY_RAND_LEN,
9277+ MBEDTLS_EXPKEY_RAND_LEN);
9278+ os_memcpy(seed + MBEDTLS_EXPKEY_RAND_LEN, conn->expkey_randbytes,
9279+ MBEDTLS_EXPKEY_RAND_LEN);
9280+
9281+ #if MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */
9282+ int ret = mbedtls_ssl_tls_prf(conn->tls_prf_type,
9283+ conn->expkey_secret, conn->expkey_secret_len,
9284+ "key expansion", seed, sizeof(seed),
9285+ tmp_out, skip + out_len);
9286+ if (ret == 0)
9287+ os_memcpy(out, tmp_out + skip, out_len);
9288+ #else
9289+ int ret = -1; /*(not reached if not impl; return -1 at top of func)*/
9290+ #endif
9291+
9292+ bin_clear_free(tmp_out, skip + out_len);
9293+ forced_memzero(seed, sizeof(seed));
9294+ return ret;
9295+}
9296+
9297+#endif /* TLS_MBEDTLS_EAP_FAST */
9298+
9299+
9300+__attribute_cold__
9301+static void tls_mbedtls_suiteb_handshake_alert (struct tls_connection *conn)
9302+{
9303+ /* tests/hwsim/test_suite_b.py test_suite_b_192_rsa_insufficient_dh */
9304+ if (!(conn->tls_conf->flags & TLS_CONN_SUITEB))
9305+ return;
9306+ if (tls_ctx_global.tls_conf) /*(is server; want issue event on client)*/
9307+ return;
9308+ #if 0
9309+ /*(info not available on client;
9310+ * mbed TLS library enforces dhm min bitlen in ServerKeyExchange)*/
9311+ if (MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 ==
9312+ #if MBEDTLS_VERSION_NUMBER < 0x03020000 /* mbedtls 3.2.0 */
9313+ mbedtls_ssl_get_ciphersuite_id_from_ssl(&conn->ssl)
9314+ #else
9315+ mbedtls_ssl_get_ciphersuite_id(
9316+ mbedtls_ssl_get_ciphersuite(&conn->ssl))
9317+ #endif
9318+ && mbedtls_mpi_size(&conn->tls_conf->conf.MBEDTLS_PRIVATE(dhm_P))
9319+ < 384 /*(3072/8)*/)
9320+ #endif
9321+ {
9322+ struct tls_config *init_conf = &tls_ctx_global.init_conf;
9323+ if (init_conf->event_cb) {
9324+ union tls_event_data ev;
9325+ os_memset(&ev, 0, sizeof(ev));
9326+ ev.alert.is_local = 1;
9327+ ev.alert.type = "fatal";
9328+ /*"internal error" string for tests/hwsim/test_suiteb.py */
9329+ ev.alert.description = "internal error: handshake failure";
9330+ /*ev.alert.description = "insufficient security";*/
9331+ init_conf->event_cb(init_conf->cb_ctx, TLS_ALERT, &ev);
9332+ }
9333+ }
9334+}
9335+
9336+
9337+struct wpabuf * tls_connection_handshake(void *tls_ctx,
9338+ struct tls_connection *conn,
9339+ const struct wpabuf *in_data,
9340+ struct wpabuf **appl_data)
9341+{
9342+ if (appl_data)
9343+ *appl_data = NULL;
9344+
9345+ if (in_data && wpabuf_len(in_data)) {
9346+ /*(unsure why tls_gnutls.c discards buffer contents; skip here)*/
9347+ if (conn->pull_buf && 0) /* disable; appears unwise */
9348+ tls_pull_buf_discard(conn, __func__);
9349+ if (!tls_pull_buf_append(conn, in_data))
9350+ return NULL;
9351+ }
9352+
9353+ if (conn->tls_conf == NULL) {
9354+ struct tls_connection_params params;
9355+ os_memset(&params, 0, sizeof(params));
9356+ params.openssl_ciphers =
9357+ tls_ctx_global.init_conf.openssl_ciphers;
9358+ params.flags = tls_ctx_global.tls_conf->flags;
9359+ if (tls_connection_set_params(tls_ctx, conn, &params) != 0)
9360+ return NULL;
9361+ }
9362+
9363+ if (conn->verify_peer) /*(call here might be redundant; nbd)*/
9364+ mbedtls_ssl_set_verify(&conn->ssl, tls_mbedtls_verify_cb, conn);
9365+
9366+ #ifdef TLS_MBEDTLS_SESSION_TICKETS
9367+ if (conn->clienthello_session_ticket)
9368+ /*(starting handshake for EAP-FAST and EAP-TEAP)*/
9369+ tls_mbedtls_clienthello_session_ticket_set(conn);
9370+
9371+ /* (not thread-safe due to need to set userdata 'conn' for callback) */
9372+ /* (unable to use mbedtls_ssl_set_user_data_p() with mbedtls 3.2.0+
9373+ * since ticket write and parse callbacks take (mbedtls_ssl_session *)
9374+ * param instead of (mbedtls_ssl_context *) param) */
9375+ if (conn->tls_conf->flags & TLS_CONN_DISABLE_SESSION_TICKET)
9376+ mbedtls_ssl_conf_session_tickets_cb(&conn->tls_conf->conf,
9377+ NULL, NULL, NULL);
9378+ else
9379+ mbedtls_ssl_conf_session_tickets_cb(&conn->tls_conf->conf,
9380+ tls_mbedtls_ssl_ticket_write,
9381+ tls_mbedtls_ssl_ticket_parse,
9382+ conn);
9383+ #endif
9384+
9385+ #if MBEDTLS_VERSION_NUMBER >= 0x03020000 /* mbedtls 3.2.0 */
9386+ int ret = mbedtls_ssl_handshake(&conn->ssl);
9387+ #else
9388+ int ret = 0;
9389+ while (conn->ssl.MBEDTLS_PRIVATE(state) != MBEDTLS_SSL_HANDSHAKE_OVER) {
9390+ ret = mbedtls_ssl_handshake_step(&conn->ssl);
9391+ if (ret != 0)
9392+ break;
9393+ }
9394+ #endif
9395+
9396+ #ifdef TLS_MBEDTLS_SESSION_TICKETS
9397+ mbedtls_ssl_conf_session_tickets_cb(&conn->tls_conf->conf,
9398+ tls_mbedtls_ssl_ticket_write,
9399+ tls_mbedtls_ssl_ticket_parse,
9400+ NULL);
9401+ #endif
9402+
9403+ switch (ret) {
9404+ case 0:
9405+ conn->established = 1;
9406+ if (conn->push_buf == NULL)
9407+ /* Need to return something to get final TLS ACK. */
9408+ conn->push_buf = wpabuf_alloc(0);
9409+
9410+ if (appl_data /*&& conn->pull_buf && wpabuf_len(conn->pull_buf)*/)
9411+ *appl_data = NULL; /* RFE: check for application data */
9412+ break;
9413+ case MBEDTLS_ERR_SSL_WANT_WRITE:
9414+ case MBEDTLS_ERR_SSL_WANT_READ:
9415+ case MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS:
9416+ case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS:
9417+ if (tls_ctx_global.tls_conf /*(is server)*/
9418+ && conn->established && conn->push_buf == NULL)
9419+ /* Need to return something to trigger completion of EAP-TLS. */
9420+ conn->push_buf = wpabuf_alloc(0);
9421+ break;
9422+ default:
9423+ ++conn->failed;
9424+ switch (ret) {
9425+ case MBEDTLS_ERR_SSL_CLIENT_RECONNECT:
9426+ case MBEDTLS_ERR_NET_CONN_RESET:
9427+ case MBEDTLS_ERR_NET_SEND_FAILED:
9428+ ++conn->write_alerts;
9429+ break;
9430+ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
9431+ case MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE:
9432+ #else
9433+ case MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE:
9434+ #endif
9435+ tls_mbedtls_suiteb_handshake_alert(conn);
9436+ /* fall through */
9437+ case MBEDTLS_ERR_NET_RECV_FAILED:
9438+ case MBEDTLS_ERR_SSL_CONN_EOF:
9439+ case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
9440+ case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE:
9441+ ++conn->read_alerts;
9442+ break;
9443+ default:
9444+ break;
9445+ }
9446+
9447+ ilog(ret, "mbedtls_ssl_handshake");
9448+ break;
9449+ }
9450+
9451+ struct wpabuf *out_data = conn->push_buf;
9452+ conn->push_buf = NULL;
9453+ return out_data;
9454+}
9455+
9456+
9457+struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
9458+ struct tls_connection *conn,
9459+ const struct wpabuf *in_data,
9460+ struct wpabuf **appl_data)
9461+{
9462+ conn->is_server = 1;
9463+ return tls_connection_handshake(tls_ctx, conn, in_data, appl_data);
9464+}
9465+
9466+
9467+struct wpabuf * tls_connection_encrypt(void *tls_ctx,
9468+ struct tls_connection *conn,
9469+ const struct wpabuf *in_data)
9470+{
9471+ int res = mbedtls_ssl_write(&conn->ssl,
9472+ wpabuf_head_u8(in_data), wpabuf_len(in_data));
9473+ if (res < 0) {
9474+ elog(res, "mbedtls_ssl_write");
9475+ return NULL;
9476+ }
9477+
9478+ struct wpabuf *buf = conn->push_buf;
9479+ conn->push_buf = NULL;
9480+ return buf;
9481+}
9482+
9483+
9484+struct wpabuf * tls_connection_decrypt(void *tls_ctx,
9485+ struct tls_connection *conn,
9486+ const struct wpabuf *in_data)
9487+{
9488+ int res;
9489+ struct wpabuf *out;
9490+
9491+ /*assert(in_data != NULL);*/
9492+ if (!tls_pull_buf_append(conn, in_data))
9493+ return NULL;
9494+
9495+ #if defined(MBEDTLS_ZLIB_SUPPORT) /* removed in mbedtls 3.x */
9496+ /* Add extra buffer space to handle the possibility of decrypted
9497+ * data being longer than input data due to TLS compression. */
9498+ out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
9499+ #else /* TLS compression is disabled in mbedtls 3.x */
9500+ out = wpabuf_alloc(wpabuf_len(in_data));
9501+ #endif
9502+ if (out == NULL)
9503+ return NULL;
9504+
9505+ res = mbedtls_ssl_read(&conn->ssl, wpabuf_mhead(out), wpabuf_size(out));
9506+ if (res < 0) {
9507+ #if 1 /*(seems like a different error if wpabuf_len(in_data) == 0)*/
9508+ if (res == MBEDTLS_ERR_SSL_WANT_READ)
9509+ return out;
9510+ #endif
9511+ elog(res, "mbedtls_ssl_read");
9512+ wpabuf_free(out);
9513+ return NULL;
9514+ }
9515+ wpabuf_put(out, res);
9516+
9517+ return out;
9518+}
9519+
9520+
9521+int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn)
9522+{
9523+ /* XXX: might need to detect if session resumed from TLS session ticket
9524+ * even if not special session ticket handling for EAP-FAST, EAP-TEAP */
9525+ /* (?ssl->handshake->resume during session ticket validation?) */
9526+ return conn && conn->resumed;
9527+}
9528+
9529+
9530+#ifdef TLS_MBEDTLS_EAP_FAST
9531+int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
9532+ u8 *ciphers)
9533+{
9534+ /* ciphers is list of TLS_CIPHER_* from hostap/src/crypto/tls.h */
9535+ int ids[7];
9536+ const int idsz = (int)sizeof(ids);
9537+ int nids = -1, id;
9538+ for ( ; *ciphers != TLS_CIPHER_NONE; ++ciphers) {
9539+ switch (*ciphers) {
9540+ case TLS_CIPHER_RC4_SHA:
9541+ #ifdef MBEDTLS_TLS_RSA_WITH_RC4_128_SHA
9542+ id = MBEDTLS_TLS_RSA_WITH_RC4_128_SHA;
9543+ break;
9544+ #else
9545+ continue; /*(not supported in mbedtls 3.x; ignore)*/
9546+ #endif
9547+ case TLS_CIPHER_AES128_SHA:
9548+ id = MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA;
9549+ break;
9550+ case TLS_CIPHER_RSA_DHE_AES128_SHA:
9551+ id = MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
9552+ break;
9553+ case TLS_CIPHER_ANON_DH_AES128_SHA:
9554+ continue; /*(not supported in mbedtls; ignore)*/
9555+ case TLS_CIPHER_RSA_DHE_AES256_SHA:
9556+ id = MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
9557+ break;
9558+ case TLS_CIPHER_AES256_SHA:
9559+ id = MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA;
9560+ break;
9561+ default:
9562+ return -1; /* should not happen */
9563+ }
9564+ if (++nids == idsz)
9565+ return -1; /* should not happen */
9566+ ids[nids] = id;
9567+ }
9568+ if (nids < 0)
9569+ return 0; /* nothing to do */
9570+ if (++nids == idsz)
9571+ return -1; /* should not happen */
9572+ ids[nids] = 0; /* terminate list */
9573+ ++nids;
9574+
9575+ return tls_mbedtls_set_ciphersuites(conn->tls_conf, ids, nids) ? 0 : -1;
9576+}
9577+#endif
9578+
9579+
9580+int tls_get_version(void *ssl_ctx, struct tls_connection *conn,
9581+ char *buf, size_t buflen)
9582+{
9583+ if (conn == NULL)
9584+ return -1;
9585+ os_strlcpy(buf, mbedtls_ssl_get_version(&conn->ssl), buflen);
9586+ return buf[0] != 'u' ? 0 : -1; /*(-1 if "unknown")*/
9587+}
9588+
9589+
9590+#ifdef TLS_MBEDTLS_EAP_TEAP
9591+u16 tls_connection_get_cipher_suite(struct tls_connection *conn)
9592+{
9593+ if (conn == NULL)
9594+ return 0;
9595+ return (u16)mbedtls_ssl_get_ciphersuite_id_from_ssl(&conn->ssl);
9596+}
9597+#endif
9598+
9599+
9600+int tls_get_cipher(void *tls_ctx, struct tls_connection *conn,
9601+ char *buf, size_t buflen)
9602+{
9603+ if (conn == NULL)
9604+ return -1;
9605+ const int id = mbedtls_ssl_get_ciphersuite_id_from_ssl(&conn->ssl);
9606+ return tls_mbedtls_translate_ciphername(id, buf, buflen) ? 0 : -1;
9607+}
9608+
9609+
9610+#ifdef TLS_MBEDTLS_SESSION_TICKETS
9611+
9612+int tls_connection_enable_workaround(void *tls_ctx,
9613+ struct tls_connection *conn)
9614+{
9615+ /* (see comment in src/eap_peer/eap_fast.c:eap_fast_init()) */
9616+ /* XXX: is there a relevant setting for this in mbed TLS? */
9617+ /* (do we even care that much about older CBC ciphers?) */
9618+ return 0;
9619+}
9620+
9621+
9622+int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn,
9623+ int ext_type, const u8 *data,
9624+ size_t data_len)
9625+{
9626+ /* (EAP-FAST and EAP-TEAP) */
9627+ if (ext_type == MBEDTLS_TLS_EXT_SESSION_TICKET) /*(ext_type == 35)*/
9628+ return tls_mbedtls_clienthello_session_ticket_prep(conn, data,
9629+ data_len);
9630+
9631+ return -1;
9632+}
9633+
9634+#endif /* TLS_MBEDTLS_SESSION_TICKETS */
9635+
9636+
9637+int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn)
9638+{
9639+ return conn ? conn->failed : -1;
9640+}
9641+
9642+
9643+int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn)
9644+{
9645+ return conn ? conn->read_alerts : -1;
9646+}
9647+
9648+
9649+int tls_connection_get_write_alerts(void *tls_ctx,
9650+ struct tls_connection *conn)
9651+{
9652+ return conn ? conn->write_alerts : -1;
9653+}
9654+
9655+
9656+#ifdef TLS_MBEDTLS_SESSION_TICKETS
9657+int tls_connection_set_session_ticket_cb(
9658+ void *tls_ctx, struct tls_connection *conn,
9659+ tls_session_ticket_cb cb, void *ctx)
9660+{
9661+ if (!(conn->tls_conf->flags & TLS_CONN_DISABLE_SESSION_TICKET)) {
9662+ /* (EAP-FAST and EAP-TEAP) */
9663+ conn->session_ticket_cb = cb;
9664+ conn->session_ticket_cb_ctx = ctx;
9665+ return 0;
9666+ }
9667+ return -1;
9668+}
9669+#endif
9670+
9671+
9672+int tls_get_library_version(char *buf, size_t buf_len)
9673+{
9674+ #ifndef MBEDTLS_VERSION_C
9675+ const char * const ver = "n/a";
9676+ #else
9677+ char ver[9];
9678+ mbedtls_version_get_string(ver);
9679+ #endif
9680+ return os_snprintf(buf, buf_len,
9681+ "mbed TLS build=" MBEDTLS_VERSION_STRING " run=%s", ver);
9682+}
9683+
9684+
9685+void tls_connection_set_success_data(struct tls_connection *conn,
9686+ struct wpabuf *data)
9687+{
9688+ wpabuf_free(conn->success_data);
9689+ conn->success_data = data;
9690+}
9691+
9692+
9693+void tls_connection_set_success_data_resumed(struct tls_connection *conn)
9694+{
9695+}
9696+
9697+
9698+const struct wpabuf *
9699+tls_connection_get_success_data(struct tls_connection *conn)
9700+{
9701+ return conn->success_data;
9702+}
9703+
9704+
9705+void tls_connection_remove_session(struct tls_connection *conn)
9706+{
9707+}
9708+
9709+
9710+#ifdef TLS_MBEDTLS_EAP_TEAP
9711+int tls_get_tls_unique(struct tls_connection *conn, u8 *buf, size_t max_len)
9712+{
9713+ #if defined(MBEDTLS_SSL_RENEGOTIATION) /* XXX: renegotiation or resumption? */
9714+ /* data from TLS handshake Finished message */
9715+ size_t verify_len = conn->ssl.MBEDTLS_PRIVATE(verify_data_len);
9716+ char *verify_data = (conn->is_server ^ conn->resumed)
9717+ ? conn->ssl.MBEDTLS_PRIVATE(peer_verify_data)
9718+ : conn->ssl.MBEDTLS_PRIVATE(own_verify_data);
9719+ if (verify_len && verify_len <= max_len) {
9720+ os_memcpy(buf, verify_data, verify_len);
9721+ return (int)verify_len;
9722+ }
9723+ #endif
9724+ return -1;
9725+}
9726+#endif
9727+
9728+
9729+__attribute_noinline__
9730+static void tls_mbedtls_set_peer_subject(struct tls_connection *conn, const mbedtls_x509_crt *crt)
9731+{
9732+ if (conn->peer_subject)
9733+ return;
9734+ char buf[MBEDTLS_X509_MAX_DN_NAME_SIZE*2];
9735+ int buflen = mbedtls_x509_dn_gets(buf, sizeof(buf), &crt->subject);
9736+ if (buflen >= 0 && (conn->peer_subject = os_malloc((size_t)buflen+1)))
9737+ os_memcpy(conn->peer_subject, buf, (size_t)buflen+1);
9738+}
9739+
9740+
9741+#ifdef TLS_MBEDTLS_EAP_TEAP
9742+const char * tls_connection_get_peer_subject(struct tls_connection *conn)
9743+{
9744+ if (!conn)
9745+ return NULL;
9746+ if (!conn->peer_subject) { /*(if not set during cert verify)*/
9747+ const mbedtls_x509_crt *peer_cert =
9748+ mbedtls_ssl_get_peer_cert(&conn->ssl);
9749+ if (peer_cert)
9750+ tls_mbedtls_set_peer_subject(conn, peer_cert);
9751+ }
9752+ return conn->peer_subject;
9753+}
9754+#endif
9755+
9756+
9757+#ifdef TLS_MBEDTLS_EAP_TEAP
9758+bool tls_connection_get_own_cert_used(struct tls_connection *conn)
9759+{
9760+ /* XXX: availability of cert does not necessary mean that client
9761+ * received certificate request from server and then sent cert.
9762+ * ? step handshake in tls_connection_handshake() looking for
9763+ * MBEDTLS_SSL_CERTIFICATE_REQUEST ? */
9764+ const struct tls_conf * const tls_conf = conn->tls_conf;
9765+ return (tls_conf->has_client_cert && tls_conf->has_private_key);
9766+}
9767+#endif
9768+
9769+
9770+#if defined(CONFIG_FIPS)
9771+#define TLS_MBEDTLS_CONFIG_FIPS
9772+#endif
9773+
9774+#if defined(CONFIG_SHA256)
9775+#define TLS_MBEDTLS_TLS_PRF_SHA256
9776+#endif
9777+
9778+#if defined(CONFIG_SHA384)
9779+#define TLS_MBEDTLS_TLS_PRF_SHA384
9780+#endif
9781+
9782+
9783+#ifndef TLS_MBEDTLS_CONFIG_FIPS
9784+#if defined(CONFIG_MODULE_TESTS)
9785+/* unused with CONFIG_TLS=mbedtls except in crypto_module_tests.c */
9786+#if MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */ \
9787+ && MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */
9788+/* sha1-tlsprf.c */
9789+#include "sha1.h"
9790+int tls_prf_sha1_md5(const u8 *secret, size_t secret_len, const char *label,
9791+ const u8 *seed, size_t seed_len, u8 *out, size_t outlen)
9792+{
9793+ return mbedtls_ssl_tls_prf(MBEDTLS_SSL_TLS_PRF_TLS1,
9794+ secret, secret_len, label,
9795+ seed, seed_len, out, outlen) ? -1 : 0;
9796+}
9797+#else
9798+#include "sha1-tlsprf.c" /* pull in hostap local implementation */
9799+#endif
9800+#endif
9801+#endif
9802+
9803+#ifdef TLS_MBEDTLS_TLS_PRF_SHA256
9804+/* sha256-tlsprf.c */
9805+#if MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */
9806+#include "sha256.h"
9807+int tls_prf_sha256(const u8 *secret, size_t secret_len, const char *label,
9808+ const u8 *seed, size_t seed_len, u8 *out, size_t outlen)
9809+{
9810+ return mbedtls_ssl_tls_prf(MBEDTLS_SSL_TLS_PRF_SHA256,
9811+ secret, secret_len, label,
9812+ seed, seed_len, out, outlen) ? -1 : 0;
9813+}
9814+#else
9815+#include "sha256-tlsprf.c" /* pull in hostap local implementation */
9816+#endif
9817+#endif
9818+
9819+#ifdef TLS_MBEDTLS_TLS_PRF_SHA384
9820+/* sha384-tlsprf.c */
9821+#if MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */
9822+#include "sha384.h"
9823+int tls_prf_sha384(const u8 *secret, size_t secret_len, const char *label,
9824+ const u8 *seed, size_t seed_len, u8 *out, size_t outlen)
9825+{
9826+ return mbedtls_ssl_tls_prf(MBEDTLS_SSL_TLS_PRF_SHA384,
9827+ secret, secret_len, label,
9828+ seed, seed_len, out, outlen) ? -1 : 0;
9829+}
9830+#else
9831+#include "sha384-tlsprf.c" /* pull in hostap local implementation */
9832+#endif
9833+#endif
9834+
9835+
9836+#if MBEDTLS_VERSION_NUMBER < 0x03020000 /* mbedtls 3.2.0 */
9837+#define mbedtls_x509_crt_has_ext_type(crt, ext_type) \
9838+ ((crt)->MBEDTLS_PRIVATE(ext_types) & (ext_type))
9839+#endif
9840+
9841+struct mlist { const char *p; size_t n; };
9842+
9843+
9844+static int
9845+tls_mbedtls_match_altsubject(mbedtls_x509_crt *crt, const char *match)
9846+{
9847+ /* RFE: this could be pre-parsed into structured data at config time */
9848+ struct mlist list[256]; /*(much larger than expected)*/
9849+ int nlist = 0;
9850+ if ( os_strncmp(match, "EMAIL:", 6) != 0
9851+ && os_strncmp(match, "DNS:", 4) != 0
9852+ && os_strncmp(match, "URI:", 4) != 0 ) {
9853+ wpa_printf(MSG_INFO, "MTLS: Invalid altSubjectName match '%s'", match);
9854+ return 0;
9855+ }
9856+ for (const char *s = match, *tok; *s; s = tok ? tok+1 : "") {
9857+ do { } while ((tok = os_strchr(s, ';'))
9858+ && os_strncmp(tok+1, "EMAIL:", 6) != 0
9859+ && os_strncmp(tok+1, "DNS:", 4) != 0
9860+ && os_strncmp(tok+1, "URI:", 4) != 0);
9861+ list[nlist].p = s;
9862+ list[nlist].n = tok ? (size_t)(tok - s) : os_strlen(s);
9863+ if (list[nlist].n && ++nlist == sizeof(list)/sizeof(*list)) {
9864+ wpa_printf(MSG_INFO, "MTLS: excessive altSubjectName match '%s'",
9865+ match);
9866+ break; /* truncate huge list and continue */
9867+ }
9868+ }
9869+
9870+ if (!mbedtls_x509_crt_has_ext_type(crt, MBEDTLS_X509_EXT_SUBJECT_ALT_NAME))
9871+ return 0;
9872+
9873+ const mbedtls_x509_sequence *cur = &crt->subject_alt_names;
9874+ for (; cur != NULL; cur = cur->next) {
9875+ const unsigned char san_type = (unsigned char)cur->buf.tag
9876+ & MBEDTLS_ASN1_TAG_VALUE_MASK;
9877+ char t;
9878+ size_t step = 4;
9879+ switch (san_type) { /* "EMAIL:" or "DNS:" or "URI:" */
9880+ case MBEDTLS_X509_SAN_RFC822_NAME: step = 6; t = 'E'; break;
9881+ case MBEDTLS_X509_SAN_DNS_NAME: t = 'D'; break;
9882+ case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: t = 'U'; break;
9883+ default: continue;
9884+ }
9885+
9886+ for (int i = 0; i < nlist; ++i) {
9887+ /* step over "EMAIL:" or "DNS:" or "URI:" in list[i].p */
9888+ /* Note: v is not '\0'-terminated, but is a known length vlen,
9889+ * so okay to pass to os_strncasecmp() even though not z-string */
9890+ if (cur->buf.len == list[i].n - step && t == *list[i].p
9891+ && 0 == os_strncasecmp((char *)cur->buf.p,
9892+ list[i].p+step, cur->buf.len)) {
9893+ return 1; /* match */
9894+ }
9895+ }
9896+ }
9897+ return 0; /* no match */
9898+}
9899+
9900+
9901+static int
9902+tls_mbedtls_match_suffix(const char *v, size_t vlen,
9903+ const struct mlist *list, int nlist, int full)
9904+{
9905+ /* Note: v is not '\0'-terminated, but is a known length vlen,
9906+ * so okay to pass to os_strncasecmp() even though not z-string */
9907+ for (int i = 0; i < nlist; ++i) {
9908+ size_t n = list[i].n;
9909+ if ((n == vlen || (n < vlen && v[vlen-n-1] == '.' && !full))
9910+ && 0 == os_strncasecmp(v+vlen-n, list[i].p, n))
9911+ return 1; /* match */
9912+ }
9913+ return 0; /* no match */
9914+}
9915+
9916+
9917+static int
9918+tls_mbedtls_match_suffixes(mbedtls_x509_crt *crt, const char *match, int full)
9919+{
9920+ /* RFE: this could be pre-parsed into structured data at config time */
9921+ struct mlist list[256]; /*(much larger than expected)*/
9922+ int nlist = 0;
9923+ for (const char *s = match, *tok; *s; s = tok ? tok+1 : "") {
9924+ tok = os_strchr(s, ';');
9925+ list[nlist].p = s;
9926+ list[nlist].n = tok ? (size_t)(tok - s) : os_strlen(s);
9927+ if (list[nlist].n && ++nlist == sizeof(list)/sizeof(*list)) {
9928+ wpa_printf(MSG_INFO, "MTLS: excessive suffix match '%s'", match);
9929+ break; /* truncate huge list and continue */
9930+ }
9931+ }
9932+
9933+ /* check subjectAltNames */
9934+ if (mbedtls_x509_crt_has_ext_type(crt, MBEDTLS_X509_EXT_SUBJECT_ALT_NAME)) {
9935+ const mbedtls_x509_sequence *cur = &crt->subject_alt_names;
9936+ for (; cur != NULL; cur = cur->next) {
9937+ const unsigned char san_type = (unsigned char)cur->buf.tag
9938+ & MBEDTLS_ASN1_TAG_VALUE_MASK;
9939+ if (san_type == MBEDTLS_X509_SAN_DNS_NAME
9940+ && tls_mbedtls_match_suffix((char *)cur->buf.p,
9941+ cur->buf.len,
9942+ list, nlist, full)) {
9943+ return 1; /* match */
9944+ }
9945+ }
9946+ }
9947+
9948+ /* check subject CN */
9949+ const mbedtls_x509_name *name = &crt->subject;
9950+ for (; name != NULL; name = name->next) {
9951+ if (name->oid.p && MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid) == 0)
9952+ break;
9953+ }
9954+ if (name && tls_mbedtls_match_suffix((char *)name->val.p, name->val.len,
9955+ list, nlist, full)) {
9956+ return 1; /* match */
9957+ }
9958+
9959+ return 0; /* no match */
9960+}
9961+
9962+
9963+static int
9964+tls_mbedtls_match_dn_field(mbedtls_x509_crt *crt, const char *match)
9965+{
9966+ /* RFE: this could be pre-parsed into structured data at config time */
9967+ struct mlistoid { const char *p; size_t n;
9968+ const char *oid; size_t olen;
9969+ int prefix; };
9970+ struct mlistoid list[32]; /*(much larger than expected)*/
9971+ int nlist = 0;
9972+ for (const char *s = match, *tok, *e; *s; s = tok ? tok+1 : "") {
9973+ tok = os_strchr(s, '/');
9974+ list[nlist].oid = NULL;
9975+ list[nlist].olen = 0;
9976+ list[nlist].n = tok ? (size_t)(tok - s) : os_strlen(s);
9977+ e = memchr(s, '=', list[nlist].n);
9978+ if (e == NULL) {
9979+ if (list[nlist].n == 0)
9980+ continue; /* skip consecutive, repeated '/' */
9981+ if (list[nlist].n == 1 && *s == '*') {
9982+ /* special-case "*" to match any OID and value */
9983+ s = e = "=*";
9984+ list[nlist].n = 2;
9985+ list[nlist].oid = "";
9986+ }
9987+ else {
9988+ wpa_printf(MSG_INFO,
9989+ "MTLS: invalid check_cert_subject '%s' missing '='",
9990+ match);
9991+ return 0;
9992+ }
9993+ }
9994+ switch (e - s) {
9995+ case 1:
9996+ if (*s == 'C') {
9997+ list[nlist].oid = MBEDTLS_OID_AT_COUNTRY;
9998+ list[nlist].olen = sizeof(MBEDTLS_OID_AT_COUNTRY)-1;
9999+ }
10000+ else if (*s == 'L') {
10001+ list[nlist].oid = MBEDTLS_OID_AT_LOCALITY;
10002+ list[nlist].olen = sizeof(MBEDTLS_OID_AT_LOCALITY)-1;
10003+ }
10004+ else if (*s == 'O') {
10005+ list[nlist].oid = MBEDTLS_OID_AT_ORGANIZATION;
10006+ list[nlist].olen = sizeof(MBEDTLS_OID_AT_ORGANIZATION)-1;
10007+ }
10008+ break;
10009+ case 2:
10010+ if (s[0] == 'C' && s[1] == 'N') {
10011+ list[nlist].oid = MBEDTLS_OID_AT_CN;
10012+ list[nlist].olen = sizeof(MBEDTLS_OID_AT_CN)-1;
10013+ }
10014+ else if (s[0] == 'S' && s[1] == 'T') {
10015+ list[nlist].oid = MBEDTLS_OID_AT_STATE;
10016+ list[nlist].olen = sizeof(MBEDTLS_OID_AT_STATE)-1;
10017+ }
10018+ else if (s[0] == 'O' && s[1] == 'U') {
10019+ list[nlist].oid = MBEDTLS_OID_AT_ORG_UNIT;
10020+ list[nlist].olen = sizeof(MBEDTLS_OID_AT_ORG_UNIT)-1;
10021+ }
10022+ break;
10023+ case 12:
10024+ if (os_memcmp(s, "emailAddress", 12) == 0) {
10025+ list[nlist].oid = MBEDTLS_OID_PKCS9_EMAIL;
10026+ list[nlist].olen = sizeof(MBEDTLS_OID_PKCS9_EMAIL)-1;
10027+ }
10028+ break;
10029+ default:
10030+ break;
10031+ }
10032+ if (list[nlist].oid == NULL) {
10033+ wpa_printf(MSG_INFO,
10034+ "MTLS: Unknown field in check_cert_subject '%s'",
10035+ match);
10036+ return 0;
10037+ }
10038+ list[nlist].n -= (size_t)(++e - s);
10039+ list[nlist].p = e;
10040+ if (list[nlist].n && e[list[nlist].n-1] == '*') {
10041+ --list[nlist].n;
10042+ list[nlist].prefix = 1;
10043+ }
10044+ /*(could easily add support for suffix matches if value begins with '*',
10045+ * but suffix match is not currently supported by other TLS modules)*/
10046+
10047+ if (list[nlist].n && ++nlist == sizeof(list)/sizeof(*list)) {
10048+ wpa_printf(MSG_INFO,
10049+ "MTLS: excessive check_cert_subject match '%s'",
10050+ match);
10051+ break; /* truncate huge list and continue */
10052+ }
10053+ }
10054+
10055+ /* each component in match string must match cert Subject in order listed
10056+ * The behavior below preserves ordering but is slightly different than
10057+ * the grossly inefficient contortions implemented in tls_openssl.c */
10058+ const mbedtls_x509_name *name = &crt->subject;
10059+ for (int i = 0; i < nlist; ++i) {
10060+ int found = 0;
10061+ for (; name != NULL && !found; name = name->next) {
10062+ if (!name->oid.p)
10063+ continue;
10064+ /* special-case "*" to match any OID and value */
10065+ if (list[i].olen == 0) {
10066+ found = 1;
10067+ continue;
10068+ }
10069+ /* perform equalent of !MBEDTLS_OID_CMP() with oid ptr and len */
10070+ if (list[i].olen != name->oid.len
10071+ || os_memcmp(list[i].oid, name->oid.p, name->oid.len) != 0)
10072+ continue;
10073+ /* Note: v is not '\0'-terminated, but is a known length vlen,
10074+ * so okay to pass to os_strncasecmp() even though not z-string */
10075+ if ((list[i].prefix
10076+ ? list[i].n <= name->val.len /* prefix match */
10077+ : list[i].n == name->val.len) /* full match */
10078+ && 0 == os_strncasecmp((char *)name->val.p,
10079+ list[i].p, list[i].n)) {
10080+ found = 1;
10081+ continue;
10082+ }
10083+ }
10084+ if (!found)
10085+ return 0; /* no match */
10086+ }
10087+ return 1; /* match */
10088+}
10089+
10090+
10091+__attribute_cold__
10092+static void
10093+tls_mbedtls_verify_fail_event (mbedtls_x509_crt *crt, int depth,
10094+ const char *errmsg, enum tls_fail_reason reason)
10095+{
10096+ struct tls_config *init_conf = &tls_ctx_global.init_conf;
10097+ if (init_conf->event_cb == NULL)
10098+ return;
10099+
10100+ struct wpabuf *certbuf = wpabuf_alloc_copy(crt->raw.p, crt->raw.len);
10101+ char subject[MBEDTLS_X509_MAX_DN_NAME_SIZE*2];
10102+ if (mbedtls_x509_dn_gets(subject, sizeof(subject), &crt->subject) < 0)
10103+ subject[0] = '\0';
10104+ union tls_event_data ev;
10105+ os_memset(&ev, 0, sizeof(ev));
10106+ ev.cert_fail.reason = reason;
10107+ ev.cert_fail.depth = depth;
10108+ ev.cert_fail.subject = subject;
10109+ ev.cert_fail.reason_txt = errmsg;
10110+ ev.cert_fail.cert = certbuf;
10111+
10112+ init_conf->event_cb(init_conf->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
10113+
10114+ wpabuf_free(certbuf);
10115+}
10116+
10117+
10118+__attribute_noinline__
10119+static void
10120+tls_mbedtls_verify_cert_event (struct tls_connection *conn,
10121+ mbedtls_x509_crt *crt, int depth)
10122+{
10123+ struct tls_config *init_conf = &tls_ctx_global.init_conf;
10124+ if (init_conf->event_cb == NULL)
10125+ return;
10126+
10127+ struct wpabuf *certbuf = NULL;
10128+ union tls_event_data ev;
10129+ os_memset(&ev, 0, sizeof(ev));
10130+
10131+ #ifdef MBEDTLS_SHA256_C
10132+ u8 hash[SHA256_DIGEST_LENGTH];
10133+ const u8 *addr[] = { (u8 *)crt->raw.p };
10134+ if (sha256_vector(1, addr, &crt->raw.len, hash) == 0) {
10135+ ev.peer_cert.hash = hash;
10136+ ev.peer_cert.hash_len = sizeof(hash);
10137+ }
10138+ #endif
10139+ ev.peer_cert.depth = depth;
10140+ char subject[MBEDTLS_X509_MAX_DN_NAME_SIZE*2];
10141+ if (depth == 0)
10142+ ev.peer_cert.subject = conn->peer_subject;
10143+ if (ev.peer_cert.subject == NULL) {
10144+ ev.peer_cert.subject = subject;
10145+ if (mbedtls_x509_dn_gets(subject, sizeof(subject), &crt->subject) < 0)
10146+ subject[0] = '\0';
10147+ }
10148+
10149+ char serial_num[128+1];
10150+ ev.peer_cert.serial_num =
10151+ tls_mbedtls_peer_serial_num(crt, serial_num, sizeof(serial_num));
10152+
10153+ const mbedtls_x509_sequence *cur;
10154+
10155+ cur = NULL;
10156+ if (mbedtls_x509_crt_has_ext_type(crt, MBEDTLS_X509_EXT_SUBJECT_ALT_NAME))
10157+ cur = &crt->subject_alt_names;
10158+ for (; cur != NULL; cur = cur->next) {
10159+ const unsigned char san_type = (unsigned char)cur->buf.tag
10160+ & MBEDTLS_ASN1_TAG_VALUE_MASK;
10161+ size_t prelen = 4;
10162+ const char *pre;
10163+ switch (san_type) {
10164+ case MBEDTLS_X509_SAN_RFC822_NAME: prelen = 6; pre = "EMAIL:";break;
10165+ case MBEDTLS_X509_SAN_DNS_NAME: pre = "DNS:"; break;
10166+ case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: pre = "URI:"; break;
10167+ default: continue;
10168+ }
10169+
10170+ char *pos = os_malloc(prelen + cur->buf.len + 1);
10171+ if (pos == NULL)
10172+ break;
10173+ ev.peer_cert.altsubject[ev.peer_cert.num_altsubject] = pos;
10174+ os_memcpy(pos, pre, prelen);
10175+ /* data should be properly backslash-escaped if needed,
10176+ * so code below does not re-escape, but does replace CTLs */
10177+ /*os_memcpy(pos+prelen, cur->buf.p, cur->buf.len);*/
10178+ /*pos[prelen+cur->buf.len] = '\0';*/
10179+ pos += prelen;
10180+ for (size_t i = 0; i < cur->buf.len; ++i) {
10181+ unsigned char c = cur->buf.p[i];
10182+ *pos++ = (c >= 32 && c != 127) ? c : '?';
10183+ }
10184+ *pos = '\0';
10185+
10186+ if (++ev.peer_cert.num_altsubject == TLS_MAX_ALT_SUBJECT)
10187+ break;
10188+ }
10189+
10190+ cur = NULL;
10191+ if (mbedtls_x509_crt_has_ext_type(crt, MBEDTLS_X509_EXT_CERTIFICATE_POLICIES))
10192+ cur = &crt->certificate_policies;
10193+ for (; cur != NULL; cur = cur->next) {
10194+ if (cur->buf.len != 11) /* len of OID_TOD_STRICT or OID_TOD_TOFU */
10195+ continue;
10196+ /* TOD-STRICT "1.3.6.1.4.1.40808.1.3.1" */
10197+ /* TOD-TOFU "1.3.6.1.4.1.40808.1.3.2" */
10198+ #define OID_TOD_STRICT "\x2b\x06\x01\x04\x01\x82\xbe\x68\x01\x03\x01"
10199+ #define OID_TOD_TOFU "\x2b\x06\x01\x04\x01\x82\xbe\x68\x01\x03\x02"
10200+ if (os_memcmp(cur->buf.p,
10201+ OID_TOD_STRICT, sizeof(OID_TOD_STRICT)-1) == 0) {
10202+ ev.peer_cert.tod = 1; /* TOD-STRICT */
10203+ break;
10204+ }
10205+ if (os_memcmp(cur->buf.p,
10206+ OID_TOD_TOFU, sizeof(OID_TOD_TOFU)-1) == 0) {
10207+ ev.peer_cert.tod = 2; /* TOD-TOFU */
10208+ break;
10209+ }
10210+ }
10211+
10212+ struct tls_conf *tls_conf = conn->tls_conf;
10213+ if (tls_conf->ca_cert_probe || (tls_conf->flags & TLS_CONN_EXT_CERT_CHECK)
10214+ || init_conf->cert_in_cb) {
10215+ certbuf = wpabuf_alloc_copy(crt->raw.p, crt->raw.len);
10216+ ev.peer_cert.cert = certbuf;
10217+ }
10218+
10219+ init_conf->event_cb(init_conf->cb_ctx, TLS_PEER_CERTIFICATE, &ev);
10220+
10221+ wpabuf_free(certbuf);
10222+ char **altsubject;
10223+ *(const char ***)&altsubject = ev.peer_cert.altsubject;
10224+ for (size_t i = 0; i < ev.peer_cert.num_altsubject; ++i)
10225+ os_free(altsubject[i]);
10226+}
10227+
10228+
10229+static int
10230+tls_mbedtls_verify_cb (void *arg, mbedtls_x509_crt *crt, int depth, uint32_t *flags)
10231+{
10232+ /* XXX: N.B. verify code not carefully tested besides hwsim tests
10233+ *
10234+ * RFE: mbedtls_x509_crt_verify_info() and enhance log trace messages
10235+ * RFE: review and add support for additional TLS_CONN_* flags
10236+ * not handling OCSP (not available in mbedtls)
10237+ * ... */
10238+
10239+ struct tls_connection *conn = (struct tls_connection *)arg;
10240+ struct tls_conf *tls_conf = conn->tls_conf;
10241+ uint32_t flags_in = *flags;
10242+
10243+ if (depth > 8) { /*(depth 8 picked as arbitrary limit)*/
10244+ emsg(MSG_WARNING, "client cert chain too long");
10245+ *flags |= MBEDTLS_X509_BADCERT_OTHER; /* cert chain too long */
10246+ tls_mbedtls_verify_fail_event(crt, depth,
10247+ "client cert chain too long",
10248+ TLS_FAIL_BAD_CERTIFICATE);
10249+ }
10250+ else if (tls_conf->verify_depth0_only) {
10251+ if (depth > 0)
10252+ *flags = 0;
10253+ else {
10254+ #ifdef MBEDTLS_SHA256_C
10255+ u8 hash[SHA256_DIGEST_LENGTH];
10256+ const u8 *addr[] = { (u8 *)crt->raw.p };
10257+ if (sha256_vector(1, addr, &crt->raw.len, hash) < 0
10258+ || os_memcmp(tls_conf->ca_cert_hash, hash, sizeof(hash)) != 0) {
10259+ *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
10260+ tls_mbedtls_verify_fail_event(crt, depth,
10261+ "cert hash mismatch",
10262+ TLS_FAIL_UNTRUSTED);
10263+ }
10264+ else /* hash matches; ignore other issues *except* if revoked)*/
10265+ *flags &= MBEDTLS_X509_BADCERT_REVOKED;
10266+ #endif
10267+ }
10268+ }
10269+ else if (depth == 0) {
10270+ if (!conn->peer_subject)
10271+ tls_mbedtls_set_peer_subject(conn, crt);
10272+ /*(use same labels to tls_mbedtls_verify_fail_event() as used in
10273+ * other TLS modules so that hwsim tests find exact string match)*/
10274+ if (!conn->peer_subject) { /* error copying subject string */
10275+ *flags |= MBEDTLS_X509_BADCERT_OTHER;
10276+ tls_mbedtls_verify_fail_event(crt, depth,
10277+ "internal error",
10278+ TLS_FAIL_UNSPECIFIED);
10279+ }
10280+ /*(use os_strstr() for subject match as is done in tls_mbedtls.c
10281+ * to follow the same behavior, even though a suffix match would
10282+ * make more sense. Also, note that strstr match does not
10283+ * normalize whitespace (between components) for comparison)*/
10284+ else if (tls_conf->subject_match
10285+ && os_strstr(conn->peer_subject,
10286+ tls_conf->subject_match) == NULL) {
10287+ wpa_printf(MSG_WARNING,
10288+ "MTLS: Subject '%s' did not match with '%s'",
10289+ conn->peer_subject, tls_conf->subject_match);
10290+ *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
10291+ tls_mbedtls_verify_fail_event(crt, depth,
10292+ "Subject mismatch",
10293+ TLS_FAIL_SUBJECT_MISMATCH);
10294+ }
10295+ if (tls_conf->altsubject_match
10296+ && !tls_mbedtls_match_altsubject(crt, tls_conf->altsubject_match)) {
10297+ wpa_printf(MSG_WARNING,
10298+ "MTLS: altSubjectName match '%s' not found",
10299+ tls_conf->altsubject_match);
10300+ *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
10301+ tls_mbedtls_verify_fail_event(crt, depth,
10302+ "AltSubject mismatch",
10303+ TLS_FAIL_ALTSUBJECT_MISMATCH);
10304+ }
10305+ if (tls_conf->suffix_match
10306+ && !tls_mbedtls_match_suffixes(crt, tls_conf->suffix_match, 0)) {
10307+ wpa_printf(MSG_WARNING,
10308+ "MTLS: Domain suffix match '%s' not found",
10309+ tls_conf->suffix_match);
10310+ *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
10311+ tls_mbedtls_verify_fail_event(crt, depth,
10312+ "Domain suffix mismatch",
10313+ TLS_FAIL_DOMAIN_SUFFIX_MISMATCH);
10314+ }
10315+ if (tls_conf->domain_match
10316+ && !tls_mbedtls_match_suffixes(crt, tls_conf->domain_match, 1)) {
10317+ wpa_printf(MSG_WARNING,
10318+ "MTLS: Domain match '%s' not found",
10319+ tls_conf->domain_match);
10320+ *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
10321+ tls_mbedtls_verify_fail_event(crt, depth,
10322+ "Domain mismatch",
10323+ TLS_FAIL_DOMAIN_MISMATCH);
10324+ }
10325+ if (tls_conf->check_cert_subject
10326+ && !tls_mbedtls_match_dn_field(crt, tls_conf->check_cert_subject)) {
10327+ *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
10328+ tls_mbedtls_verify_fail_event(crt, depth,
10329+ "Distinguished Name",
10330+ TLS_FAIL_DN_MISMATCH);
10331+ }
10332+ if (tls_conf->flags & TLS_CONN_SUITEB) {
10333+ /* check RSA modulus size (public key bitlen) */
10334+ const mbedtls_pk_type_t pk_alg = mbedtls_pk_get_type(&crt->pk);
10335+ if ((pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS)
10336+ && mbedtls_pk_get_bitlen(&crt->pk) < 3072) {
10337+ /* hwsim suite_b RSA tests expect 3072
10338+ * suite_b_192_rsa_ecdhe_radius_rsa2048_client
10339+ * suite_b_192_rsa_dhe_radius_rsa2048_client */
10340+ *flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
10341+ tls_mbedtls_verify_fail_event(crt, depth,
10342+ "Insufficient RSA modulus size",
10343+ TLS_FAIL_INSUFFICIENT_KEY_LEN);
10344+ }
10345+ }
10346+ if (tls_conf->check_crl && tls_conf->crl == NULL) {
10347+ /* see tests/hwsim test_ap_eap.py ap_wpa2_eap_tls_check_crl */
10348+ emsg(MSG_WARNING, "check_crl set but no CRL loaded; reject all?");
10349+ *flags |= MBEDTLS_X509_BADCERT_OTHER;
10350+ tls_mbedtls_verify_fail_event(crt, depth,
10351+ "check_crl set but no CRL loaded; "
10352+ "reject all?",
10353+ TLS_FAIL_BAD_CERTIFICATE);
10354+ }
10355+ }
10356+ else {
10357+ if (tls_conf->check_crl != 2) /* 2 == verify CRLs for all certs */
10358+ *flags &= ~MBEDTLS_X509_BADCERT_REVOKED;
10359+ }
10360+
10361+ if (!tls_conf->check_crl_strict) {
10362+ *flags &= ~MBEDTLS_X509_BADCRL_EXPIRED;
10363+ *flags &= ~MBEDTLS_X509_BADCRL_FUTURE;
10364+ }
10365+
10366+ if (tls_conf->flags & TLS_CONN_DISABLE_TIME_CHECKS) {
10367+ *flags &= ~MBEDTLS_X509_BADCERT_EXPIRED;
10368+ *flags &= ~MBEDTLS_X509_BADCERT_FUTURE;
10369+ }
10370+
10371+ tls_mbedtls_verify_cert_event(conn, crt, depth);
10372+
10373+ if (*flags) {
10374+ if (*flags & (MBEDTLS_X509_BADCERT_NOT_TRUSTED
10375+ |MBEDTLS_X509_BADCERT_CN_MISMATCH
10376+ |MBEDTLS_X509_BADCERT_REVOKED)) {
10377+ emsg(MSG_WARNING, "client cert not trusted");
10378+ }
10379+ /* report event if flags set but no additional flags set above */
10380+ /* (could translate flags to more detailed TLS_FAIL_* if needed) */
10381+ if (!(*flags & ~flags_in)) {
10382+ enum tls_fail_reason reason = TLS_FAIL_UNSPECIFIED;
10383+ const char *errmsg = "cert verify fail unspecified";
10384+ if (*flags & MBEDTLS_X509_BADCERT_NOT_TRUSTED) {
10385+ reason = TLS_FAIL_UNTRUSTED;
10386+ errmsg = "certificate not trusted";
10387+ }
10388+ if (*flags & MBEDTLS_X509_BADCERT_REVOKED) {
10389+ reason = TLS_FAIL_REVOKED;
10390+ errmsg = "certificate has been revoked";
10391+ }
10392+ if (*flags & MBEDTLS_X509_BADCERT_FUTURE) {
10393+ reason = TLS_FAIL_NOT_YET_VALID;
10394+ errmsg = "certificate not yet valid";
10395+ }
10396+ if (*flags & MBEDTLS_X509_BADCERT_EXPIRED) {
10397+ reason = TLS_FAIL_EXPIRED;
10398+ errmsg = "certificate has expired";
10399+ }
10400+ if (*flags & MBEDTLS_X509_BADCERT_BAD_MD) {
10401+ reason = TLS_FAIL_BAD_CERTIFICATE;
10402+ errmsg = "certificate uses insecure algorithm";
10403+ }
10404+ tls_mbedtls_verify_fail_event(crt, depth, errmsg, reason);
10405+ }
10406+ #if 0
10407+ /* ??? send (again) cert events for all certs in chain ???
10408+ * (should already have been called for greater depths) */
10409+ /* tls_openssl.c:tls_verify_cb() sends cert events for all certs
10410+ * in chain if certificate validation fails, but sends all events
10411+ * with depth set to 0 (might be a bug) */
10412+ if (depth > 0) {
10413+ int pdepth = depth + 1;
10414+ for (mbedtls_x509_crt *pcrt; (pcrt = crt->next); ++pdepth) {
10415+ tls_mbedtls_verify_cert_event(conn, pcrt, pdepth);
10416+ }
10417+ }
10418+ #endif
10419+ /*(do not preserve subject if verification failed but was optional)*/
10420+ if (depth == 0 && conn->peer_subject) {
10421+ os_free(conn->peer_subject);
10422+ conn->peer_subject = NULL;
10423+ }
10424+ }
10425+ else if (depth == 0) {
10426+ struct tls_config *init_conf = &tls_ctx_global.init_conf;
10427+ if (tls_conf->ca_cert_probe) {
10428+ /* reject server certificate on probe-only run */
10429+ *flags |= MBEDTLS_X509_BADCERT_OTHER;
10430+ tls_mbedtls_verify_fail_event(crt, depth,
10431+ "server chain probe",
10432+ TLS_FAIL_SERVER_CHAIN_PROBE);
10433+ }
10434+ else if (init_conf->event_cb) {
10435+ /* ??? send event as soon as depth == 0 is verified ???
10436+ * What about rest of chain?
10437+ * Follows tls_mbedtls.c behavior: */
10438+ init_conf->event_cb(init_conf->cb_ctx,
10439+ TLS_CERT_CHAIN_SUCCESS, NULL);
10440+ }
10441+ }
10442+
10443+ return 0;
10444+}
10445diff --git a/src/drivers/driver.h b/src/drivers/driver.h
10446index e672a1787..3e3e309f4 100644
10447--- a/src/drivers/driver.h
10448+++ b/src/drivers/driver.h
10449@@ -971,6 +971,9 @@ struct wpa_driver_associate_params {
10450 * responsible for selecting with which BSS to associate. */
10451 const u8 *bssid;
10452
10453+ unsigned char rates[32];
10454+ int mcast_rate;
10455+
10456 /**
10457 * bssid_hint - BSSID of a proposed AP
10458 *
10459@@ -1873,6 +1876,7 @@ struct wpa_driver_mesh_join_params {
10460 #define WPA_DRIVER_MESH_FLAG_AMPE 0x00000008
10461 unsigned int flags;
10462 bool handle_dfs;
10463+ int mcast_rate;
10464 };
10465
10466 struct wpa_driver_set_key_params {
10467@@ -2340,6 +2344,9 @@ struct wpa_driver_capa {
10468 /** Maximum number of iterations in a single scan plan */
10469 u32 max_sched_scan_plan_iterations;
10470
10471+ /** Maximum number of extra IE bytes for scans */
10472+ u16 max_scan_ie_len;
10473+
10474 /** Whether sched_scan (offloaded scanning) is supported */
10475 int sched_scan_supported;
10476
10477@@ -3861,6 +3868,25 @@ struct wpa_driver_ops {
10478 int (*if_remove)(void *priv, enum wpa_driver_if_type type,
10479 const char *ifname);
10480
10481+ /**
10482+ * if_rename - Rename a virtual interface
10483+ * @priv: Private driver interface data
10484+ * @type: Interface type
10485+ * @ifname: Interface name of the virtual interface to be renamed
10486+ * (NULL when renaming the AP BSS interface)
10487+ * @new_name: New interface name of the virtual interface
10488+ * Returns: 0 on success, -1 on failure
10489+ */
10490+ int (*if_rename)(void *priv, enum wpa_driver_if_type type,
10491+ const char *ifname, const char *new_name);
10492+
10493+ /**
10494+ * set_first_bss - Make a virtual interface the first (primary) bss
10495+ * @priv: Private driver interface data
10496+ * Returns: 0 on success, -1 on failure
10497+ */
10498+ int (*set_first_bss)(void *priv);
10499+
10500 /**
10501 * set_sta_vlan - Bind a station into a specific interface (AP only)
10502 * @priv: Private driver interface data
10503@@ -4265,7 +4291,7 @@ struct wpa_driver_ops {
10504 * Returns: 0 on success, negative (<0) on failure
10505 */
10506 int (*br_set_net_param)(void *priv, enum drv_br_net_param param,
10507- unsigned int val);
10508+ const char *ifname, unsigned int val);
10509
10510 /**
10511 * get_wowlan - Get wake-on-wireless status
10512@@ -6559,6 +6585,7 @@ union wpa_event_data {
10513
10514 /**
10515 * struct ch_switch
10516+ * @count: Count until channel switch activates
10517 * @freq: Frequency of new channel in MHz
10518 * @ht_enabled: Whether this is an HT channel
10519 * @ch_offset: Secondary channel offset
10520@@ -6569,6 +6596,7 @@ union wpa_event_data {
10521 * @punct_bitmap: Puncturing bitmap
10522 */
10523 struct ch_switch {
10524+ int count;
10525 int freq;
10526 int ht_enabled;
10527 int ch_offset;
10528@@ -6816,8 +6844,8 @@ union wpa_event_data {
10529 * Driver wrapper code should call this function whenever an event is received
10530 * from the driver.
10531 */
10532-void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
10533- union wpa_event_data *data);
10534+extern void (*wpa_supplicant_event)(void *ctx, enum wpa_event_type event,
10535+ union wpa_event_data *data);
10536
10537 /**
10538 * wpa_supplicant_event_global - Report a driver event for wpa_supplicant
10539@@ -6829,7 +6857,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
10540 * Same as wpa_supplicant_event(), but we search for the interface in
10541 * wpa_global.
10542 */
10543-void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
10544+extern void (*wpa_supplicant_event_global)(void *ctx, enum wpa_event_type event,
10545 union wpa_event_data *data);
10546
10547 /*
10548diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
10549index 9ac621ae6..6778ad369 100644
10550--- a/src/drivers/driver_nl80211.c
10551+++ b/src/drivers/driver_nl80211.c
10552@@ -78,6 +78,16 @@ enum nlmsgerr_attrs {
10553
10554 #endif /* ANDROID */
10555
10556+static void handle_nl_debug_hook(struct nl_msg *msg, int tx)
10557+{
10558+ const struct nlmsghdr *nlh;
10559+
10560+ if (!wpa_netlink_hook)
10561+ return;
10562+
10563+ nlh = nlmsg_hdr(msg);
10564+ wpa_netlink_hook(tx, nlh, nlh->nlmsg_len);
10565+}
10566
10567 static struct nl_sock * nl_create_handle(struct nl_cb *cb, const char *dbg)
10568 {
10569@@ -432,6 +442,11 @@ static int no_seq_check(struct nl_msg *msg, void *arg)
10570 return NL_OK;
10571 }
10572
10573+static int debug_handler(struct nl_msg *msg, void *arg)
10574+{
10575+ handle_nl_debug_hook(msg, 0);
10576+ return NL_OK;
10577+}
10578
10579 static void nl80211_nlmsg_clear(struct nl_msg *msg)
10580 {
10581@@ -505,6 +520,7 @@ int send_and_recv(struct nl80211_global *global,
10582 if (!msg)
10583 return -ENOMEM;
10584
10585+ handle_nl_debug_hook(msg, 1);
10586 err.err = -ENOMEM;
10587
10588 s_nl_cb = nl_socket_get_cb(nl_handle);
10589@@ -539,6 +555,7 @@ int send_and_recv(struct nl80211_global *global,
10590 err.orig_msg = msg;
10591 err.err_info = err_info;
10592
10593+ nl_cb_set(cb, NL_CB_MSG_IN, NL_CB_CUSTOM, debug_handler, NULL);
10594 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
10595 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err.err);
10596 if (ack_handler_custom) {
10597@@ -942,6 +959,7 @@ nl80211_get_wiphy_data_ap(struct i802_bss *bss)
10598 os_free(w);
10599 return NULL;
10600 }
10601+ nl_cb_set(w->nl_cb, NL_CB_MSG_IN, NL_CB_CUSTOM, debug_handler, NULL);
10602 nl_cb_set(w->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
10603 no_seq_check, NULL);
10604 nl_cb_set(w->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
10605@@ -1356,7 +1374,7 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
10606 }
10607 wpa_printf(MSG_DEBUG, "nl80211: Interface down (%s/%s)",
10608 namebuf, ifname);
10609- if (os_strcmp(drv->first_bss->ifname, ifname) != 0) {
10610+ if (drv->first_bss->ifindex != ifi->ifi_index) {
10611 wpa_printf(MSG_DEBUG,
10612 "nl80211: Not the main interface (%s) - do not indicate interface down",
10613 drv->first_bss->ifname);
10614@@ -1392,7 +1410,7 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
10615 }
10616 wpa_printf(MSG_DEBUG, "nl80211: Interface up (%s/%s)",
10617 namebuf, ifname);
10618- if (os_strcmp(drv->first_bss->ifname, ifname) != 0) {
10619+ if (drv->first_bss->ifindex != ifi->ifi_index) {
10620 wpa_printf(MSG_DEBUG,
10621 "nl80211: Not the main interface (%s) - do not indicate interface up",
10622 drv->first_bss->ifname);
10623@@ -2038,6 +2056,7 @@ static int wpa_driver_nl80211_init_nl_global(struct nl80211_global *global)
10624 genl_family_put(family);
10625 nl_cache_free(cache);
10626
10627+ nl_cb_set(global->nl_cb, NL_CB_MSG_IN, NL_CB_CUSTOM, debug_handler, NULL);
10628 nl_cb_set(global->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
10629 no_seq_check, NULL);
10630 nl_cb_set(global->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
10631@@ -2208,6 +2227,7 @@ static int nl80211_init_bss(struct i802_bss *bss)
10632 if (!bss->nl_cb)
10633 return -1;
10634
10635+ nl_cb_set(bss->nl_cb, NL_CB_MSG_IN, NL_CB_CUSTOM, debug_handler, NULL);
10636 nl_cb_set(bss->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
10637 no_seq_check, NULL);
10638 nl_cb_set(bss->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
10639@@ -5485,7 +5505,7 @@ static int nl80211_set_channel(struct i802_bss *bss,
10640 freq->he_enabled, freq->eht_enabled, freq->bandwidth,
10641 freq->center_freq1, freq->center_freq2);
10642
10643- msg = nl80211_drv_msg(drv, 0, set_chan ? NL80211_CMD_SET_CHANNEL :
10644+ msg = nl80211_bss_msg(bss, 0, set_chan ? NL80211_CMD_SET_CHANNEL :
10645 NL80211_CMD_SET_WIPHY);
10646 if (!msg || nl80211_put_freq_params(msg, freq) < 0) {
10647 nlmsg_free(msg);
10648@@ -5858,26 +5878,29 @@ fail:
10649
10650 static void rtnl_neigh_delete_fdb_entry(struct i802_bss *bss, const u8 *addr)
10651 {
10652-#ifdef CONFIG_LIBNL3_ROUTE
10653 struct wpa_driver_nl80211_data *drv = bss->drv;
10654- struct rtnl_neigh *rn;
10655- struct nl_addr *nl_addr;
10656+ struct ndmsg nhdr = {
10657+ .ndm_state = NUD_PERMANENT,
10658+ .ndm_ifindex = bss->ifindex,
10659+ .ndm_family = AF_BRIDGE,
10660+ };
10661+ struct nl_msg *msg;
10662 int err;
10663
10664- rn = rtnl_neigh_alloc();
10665- if (!rn)
10666+ msg = nlmsg_alloc_simple(RTM_DELNEIGH, NLM_F_CREATE);
10667+ if (!msg)
10668 return;
10669
10670- rtnl_neigh_set_family(rn, AF_BRIDGE);
10671- rtnl_neigh_set_ifindex(rn, bss->ifindex);
10672- nl_addr = nl_addr_build(AF_BRIDGE, (void *) addr, ETH_ALEN);
10673- if (!nl_addr) {
10674- rtnl_neigh_put(rn);
10675- return;
10676- }
10677- rtnl_neigh_set_lladdr(rn, nl_addr);
10678+ if (nlmsg_append(msg, &nhdr, sizeof(nhdr), NLMSG_ALIGNTO) < 0)
10679+ goto errout;
10680
10681- err = rtnl_neigh_delete(drv->rtnl_sk, rn, 0);
10682+ if (nla_put(msg, NDA_LLADDR, ETH_ALEN, (void *)addr))
10683+ goto errout;
10684+
10685+ if (nl_send_auto_complete(drv->rtnl_sk, msg) < 0)
10686+ goto errout;
10687+
10688+ err = nl_wait_for_ack(drv->rtnl_sk);
10689 if (err < 0) {
10690 wpa_printf(MSG_DEBUG, "nl80211: bridge FDB entry delete for "
10691 MACSTR " ifindex=%d failed: %s", MAC2STR(addr),
10692@@ -5887,9 +5910,8 @@ static void rtnl_neigh_delete_fdb_entry(struct i802_bss *bss, const u8 *addr)
10693 MACSTR, MAC2STR(addr));
10694 }
10695
10696- nl_addr_put(nl_addr);
10697- rtnl_neigh_put(rn);
10698-#endif /* CONFIG_LIBNL3_ROUTE */
10699+errout:
10700+ nlmsg_free(msg);
10701 }
10702
10703
10704@@ -6178,6 +6200,8 @@ static void nl80211_teardown_ap(struct i802_bss *bss)
10705 nl80211_put_wiphy_data_ap(bss);
10706 if (bss->flink)
10707 bss->flink->beacon_set = 0;
10708+
10709+ wpa_driver_nl80211_del_beacon_all(bss);
10710 }
10711
10712
10713@@ -8566,6 +8590,7 @@ static void *i802_init(struct hostapd_data *hapd,
10714 char master_ifname[IFNAMSIZ];
10715 int ifindex, br_ifindex = 0;
10716 int br_added = 0;
10717+ int err;
10718
10719 bss = wpa_driver_nl80211_drv_init(hapd, params->ifname,
10720 params->global_priv, 1,
10721@@ -8625,24 +8650,18 @@ static void *i802_init(struct hostapd_data *hapd,
10722 (params->num_bridge == 0 || !params->bridge[0]))
10723 add_ifidx(drv, br_ifindex, drv->ifindex);
10724
10725-#ifdef CONFIG_LIBNL3_ROUTE
10726- if (bss->added_if_into_bridge || bss->already_in_bridge) {
10727- int err;
10728-
10729- drv->rtnl_sk = nl_socket_alloc();
10730- if (drv->rtnl_sk == NULL) {
10731- wpa_printf(MSG_ERROR, "nl80211: Failed to allocate nl_sock");
10732- goto failed;
10733- }
10734+ drv->rtnl_sk = nl_socket_alloc();
10735+ if (drv->rtnl_sk == NULL) {
10736+ wpa_printf(MSG_ERROR, "nl80211: Failed to allocate nl_sock");
10737+ goto failed;
10738+ }
10739
10740- err = nl_connect(drv->rtnl_sk, NETLINK_ROUTE);
10741- if (err) {
10742- wpa_printf(MSG_ERROR, "nl80211: Failed to connect nl_sock to NETLINK_ROUTE: %s",
10743- nl_geterror(err));
10744- goto failed;
10745- }
10746+ err = nl_connect(drv->rtnl_sk, NETLINK_ROUTE);
10747+ if (err) {
10748+ wpa_printf(MSG_ERROR, "nl80211: Failed to connect nl_sock to NETLINK_ROUTE: %s",
10749+ nl_geterror(err));
10750+ goto failed;
10751 }
10752-#endif /* CONFIG_LIBNL3_ROUTE */
10753
10754 if (drv->capa.flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX) {
10755 wpa_printf(MSG_DEBUG,
10756@@ -9000,6 +9019,7 @@ static int wpa_driver_nl80211_if_remove(struct i802_bss *bss,
10757 if (drv->first_bss->next) {
10758 drv->first_bss = drv->first_bss->next;
10759 drv->ctx = drv->first_bss->ctx;
10760+ drv->ifindex = drv->first_bss->ifindex;
10761 os_free(bss);
10762 } else {
10763 wpa_printf(MSG_DEBUG, "nl80211: No second BSS to reassign context to");
10764@@ -9009,6 +9029,50 @@ static int wpa_driver_nl80211_if_remove(struct i802_bss *bss,
10765 return 0;
10766 }
10767
10768+static int wpa_driver_nl80211_if_rename(struct i802_bss *bss,
10769+ enum wpa_driver_if_type type,
10770+ const char *ifname, const char *new_name)
10771+{
10772+ struct wpa_driver_nl80211_data *drv = bss->drv;
10773+ struct ifinfomsg ifi = {
10774+ .ifi_family = AF_UNSPEC,
10775+ .ifi_index = bss->ifindex,
10776+ };
10777+ struct nl_msg *msg;
10778+ int res = -ENOMEM;
10779+
10780+ if (ifname)
10781+ ifi.ifi_index = if_nametoindex(ifname);
10782+
10783+ msg = nlmsg_alloc_simple(RTM_SETLINK, 0);
10784+ if (!msg)
10785+ return res;
10786+
10787+ if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0)
10788+ goto out;
10789+
10790+ if (nla_put_string(msg, IFLA_IFNAME, new_name))
10791+ goto out;
10792+
10793+ res = nl_send_auto_complete(drv->rtnl_sk, msg);
10794+ if (res < 0)
10795+ goto out;
10796+
10797+ res = nl_wait_for_ack(drv->rtnl_sk);
10798+ if (res) {
10799+ wpa_printf(MSG_INFO,
10800+ "nl80211: Renaming device %s to %s failed: %s",
10801+ ifname ? ifname : bss->ifname, new_name, nl_geterror(res));
10802+ goto out;
10803+ }
10804+
10805+ if (type == WPA_IF_AP_BSS && !ifname)
10806+ os_strlcpy(bss->ifname, new_name, sizeof(bss->ifname));
10807+
10808+out:
10809+ nlmsg_free(msg);
10810+ return res;
10811+}
10812
10813 static int cookie_handler(struct nl_msg *msg, void *arg)
10814 {
10815@@ -10792,6 +10856,37 @@ static bool nl80211_is_drv_shared(void *priv, void *bss_ctx)
10816 #endif /* CONFIG_IEEE80211BE */
10817
10818
10819+static int driver_nl80211_if_rename(void *priv, enum wpa_driver_if_type type,
10820+ const char *ifname, const char *new_name)
10821+{
10822+ struct i802_bss *bss = priv;
10823+ return wpa_driver_nl80211_if_rename(bss, type, ifname, new_name);
10824+}
10825+
10826+
10827+static int driver_nl80211_set_first_bss(void *priv)
10828+{
10829+ struct i802_bss *bss = priv, *tbss;
10830+ struct wpa_driver_nl80211_data *drv = bss->drv;
10831+
10832+ if (drv->first_bss == bss)
10833+ return 0;
10834+
10835+ for (tbss = drv->first_bss; tbss; tbss = tbss->next) {
10836+ if (tbss->next != bss)
10837+ continue;
10838+
10839+ tbss->next = bss->next;
10840+ bss->next = drv->first_bss;
10841+ drv->first_bss = bss;
10842+ drv->ctx = bss->ctx;
10843+ return 0;
10844+ }
10845+
10846+ return -1;
10847+}
10848+
10849+
10850 static int driver_nl80211_send_mlme(void *priv, const u8 *data,
10851 size_t data_len, int noack,
10852 unsigned int freq,
10853@@ -11294,6 +11389,10 @@ static int nl80211_switch_channel(void *priv, struct csa_settings *settings)
10854 if (ret)
10855 goto error;
10856
10857+ if (drv->nlmode == NL80211_IFTYPE_MESH_POINT) {
10858+ nla_put_flag(msg, NL80211_ATTR_HANDLE_DFS);
10859+ }
10860+
10861 /* beacon_csa params */
10862 beacon_csa = nla_nest_start(msg, NL80211_ATTR_CSA_IES);
10863 if (!beacon_csa)
10864@@ -11940,6 +12039,18 @@ static int nl80211_put_mesh_id(struct nl_msg *msg, const u8 *mesh_id,
10865 }
10866
10867
10868+static int nl80211_put_mcast_rate(struct nl_msg *msg, int mcast_rate)
10869+{
10870+ if (mcast_rate > 0) {
10871+ wpa_printf(MSG_DEBUG, " * mcast_rate=%.1f",
10872+ (double)mcast_rate / 10);
10873+ return nla_put_u32(msg, NL80211_ATTR_MCAST_RATE, mcast_rate);
10874+ }
10875+
10876+ return 0;
10877+}
10878+
10879+
10880 static int nl80211_put_mesh_config(struct nl_msg *msg,
10881 struct wpa_driver_mesh_bss_params *params)
10882 {
10883@@ -12001,6 +12112,7 @@ static int nl80211_join_mesh(struct i802_bss *bss,
10884 nl80211_put_basic_rates(msg, params->basic_rates) ||
10885 nl80211_put_mesh_id(msg, params->meshid, params->meshid_len) ||
10886 nl80211_put_beacon_int(msg, params->beacon_int) ||
10887+ nl80211_put_mcast_rate(msg, params->mcast_rate) ||
10888 nl80211_put_dtim_period(msg, params->dtim_period))
10889 goto fail;
10890
10891@@ -12156,13 +12268,14 @@ static int wpa_driver_br_add_ip_neigh(void *priv, u8 version,
10892 const u8 *ipaddr, int prefixlen,
10893 const u8 *addr)
10894 {
10895-#ifdef CONFIG_LIBNL3_ROUTE
10896 struct i802_bss *bss = priv;
10897 struct wpa_driver_nl80211_data *drv = bss->drv;
10898- struct rtnl_neigh *rn;
10899- struct nl_addr *nl_ipaddr = NULL;
10900- struct nl_addr *nl_lladdr = NULL;
10901- int family, addrsize;
10902+ struct ndmsg nhdr = {
10903+ .ndm_state = NUD_PERMANENT,
10904+ .ndm_ifindex = bss->br_ifindex,
10905+ };
10906+ struct nl_msg *msg;
10907+ int addrsize;
10908 int res;
10909
10910 if (!ipaddr || prefixlen == 0 || !addr)
10911@@ -12181,85 +12294,66 @@ static int wpa_driver_br_add_ip_neigh(void *priv, u8 version,
10912 }
10913
10914 if (version == 4) {
10915- family = AF_INET;
10916+ nhdr.ndm_family = AF_INET;
10917 addrsize = 4;
10918 } else if (version == 6) {
10919- family = AF_INET6;
10920+ nhdr.ndm_family = AF_INET6;
10921 addrsize = 16;
10922 } else {
10923 return -EINVAL;
10924 }
10925
10926- rn = rtnl_neigh_alloc();
10927- if (rn == NULL)
10928+ msg = nlmsg_alloc_simple(RTM_NEWNEIGH, NLM_F_CREATE);
10929+ if (!msg)
10930 return -ENOMEM;
10931
10932- /* set the destination ip address for neigh */
10933- nl_ipaddr = nl_addr_build(family, (void *) ipaddr, addrsize);
10934- if (nl_ipaddr == NULL) {
10935- wpa_printf(MSG_DEBUG, "nl80211: nl_ipaddr build failed");
10936- res = -ENOMEM;
10937+ res = -ENOMEM;
10938+ if (nlmsg_append(msg, &nhdr, sizeof(nhdr), NLMSG_ALIGNTO) < 0)
10939 goto errout;
10940- }
10941- nl_addr_set_prefixlen(nl_ipaddr, prefixlen);
10942- res = rtnl_neigh_set_dst(rn, nl_ipaddr);
10943- if (res) {
10944- wpa_printf(MSG_DEBUG,
10945- "nl80211: neigh set destination addr failed");
10946+
10947+ if (nla_put(msg, NDA_DST, addrsize, (void *)ipaddr))
10948 goto errout;
10949- }
10950
10951- /* set the corresponding lladdr for neigh */
10952- nl_lladdr = nl_addr_build(AF_BRIDGE, (u8 *) addr, ETH_ALEN);
10953- if (nl_lladdr == NULL) {
10954- wpa_printf(MSG_DEBUG, "nl80211: neigh set lladdr failed");
10955- res = -ENOMEM;
10956+ if (nla_put(msg, NDA_LLADDR, ETH_ALEN, (void *)addr))
10957 goto errout;
10958- }
10959- rtnl_neigh_set_lladdr(rn, nl_lladdr);
10960
10961- rtnl_neigh_set_ifindex(rn, bss->br_ifindex);
10962- rtnl_neigh_set_state(rn, NUD_PERMANENT);
10963+ res = nl_send_auto_complete(drv->rtnl_sk, msg);
10964+ if (res < 0)
10965+ goto errout;
10966
10967- res = rtnl_neigh_add(drv->rtnl_sk, rn, NLM_F_CREATE);
10968+ res = nl_wait_for_ack(drv->rtnl_sk);
10969 if (res) {
10970 wpa_printf(MSG_DEBUG,
10971 "nl80211: Adding bridge ip neigh failed: %s",
10972 nl_geterror(res));
10973 }
10974 errout:
10975- if (nl_lladdr)
10976- nl_addr_put(nl_lladdr);
10977- if (nl_ipaddr)
10978- nl_addr_put(nl_ipaddr);
10979- if (rn)
10980- rtnl_neigh_put(rn);
10981+ nlmsg_free(msg);
10982 return res;
10983-#else /* CONFIG_LIBNL3_ROUTE */
10984- return -1;
10985-#endif /* CONFIG_LIBNL3_ROUTE */
10986 }
10987
10988
10989 static int wpa_driver_br_delete_ip_neigh(void *priv, u8 version,
10990 const u8 *ipaddr)
10991 {
10992-#ifdef CONFIG_LIBNL3_ROUTE
10993 struct i802_bss *bss = priv;
10994 struct wpa_driver_nl80211_data *drv = bss->drv;
10995- struct rtnl_neigh *rn;
10996- struct nl_addr *nl_ipaddr;
10997- int family, addrsize;
10998+ struct ndmsg nhdr = {
10999+ .ndm_state = NUD_PERMANENT,
11000+ .ndm_ifindex = bss->br_ifindex,
11001+ };
11002+ struct nl_msg *msg;
11003+ int addrsize;
11004 int res;
11005
11006 if (!ipaddr)
11007 return -EINVAL;
11008
11009 if (version == 4) {
11010- family = AF_INET;
11011+ nhdr.ndm_family = AF_INET;
11012 addrsize = 4;
11013 } else if (version == 6) {
11014- family = AF_INET6;
11015+ nhdr.ndm_family = AF_INET6;
11016 addrsize = 16;
11017 } else {
11018 return -EINVAL;
11019@@ -12277,41 +12371,30 @@ static int wpa_driver_br_delete_ip_neigh(void *priv, u8 version,
11020 return -1;
11021 }
11022
11023- rn = rtnl_neigh_alloc();
11024- if (rn == NULL)
11025+ msg = nlmsg_alloc_simple(RTM_DELNEIGH, NLM_F_CREATE);
11026+ if (!msg)
11027 return -ENOMEM;
11028
11029- /* set the destination ip address for neigh */
11030- nl_ipaddr = nl_addr_build(family, (void *) ipaddr, addrsize);
11031- if (nl_ipaddr == NULL) {
11032- wpa_printf(MSG_DEBUG, "nl80211: nl_ipaddr build failed");
11033- res = -ENOMEM;
11034+ res = -ENOMEM;
11035+ if (nlmsg_append(msg, &nhdr, sizeof(nhdr), NLMSG_ALIGNTO) < 0)
11036 goto errout;
11037- }
11038- res = rtnl_neigh_set_dst(rn, nl_ipaddr);
11039- if (res) {
11040- wpa_printf(MSG_DEBUG,
11041- "nl80211: neigh set destination addr failed");
11042+
11043+ if (nla_put(msg, NDA_DST, addrsize, (void *)ipaddr))
11044 goto errout;
11045- }
11046
11047- rtnl_neigh_set_ifindex(rn, bss->br_ifindex);
11048+ res = nl_send_auto_complete(drv->rtnl_sk, msg);
11049+ if (res < 0)
11050+ goto errout;
11051
11052- res = rtnl_neigh_delete(drv->rtnl_sk, rn, 0);
11053+ res = nl_wait_for_ack(drv->rtnl_sk);
11054 if (res) {
11055 wpa_printf(MSG_DEBUG,
11056 "nl80211: Deleting bridge ip neigh failed: %s",
11057 nl_geterror(res));
11058 }
11059 errout:
11060- if (nl_ipaddr)
11061- nl_addr_put(nl_ipaddr);
11062- if (rn)
11063- rtnl_neigh_put(rn);
11064+ nlmsg_free(msg);
11065 return res;
11066-#else /* CONFIG_LIBNL3_ROUTE */
11067- return -1;
11068-#endif /* CONFIG_LIBNL3_ROUTE */
11069 }
11070
11071
11072@@ -12389,7 +12472,7 @@ static const char * drv_br_net_param_str(enum drv_br_net_param param)
11073
11074
11075 static int wpa_driver_br_set_net_param(void *priv, enum drv_br_net_param param,
11076- unsigned int val)
11077+ const char *ifname, unsigned int val)
11078 {
11079 struct i802_bss *bss = priv;
11080 char path[128];
11081@@ -12415,8 +12498,11 @@ static int wpa_driver_br_set_net_param(void *priv, enum drv_br_net_param param,
11082 return -EINVAL;
11083 }
11084
11085+ if (!ifname)
11086+ ifname = bss->brname;
11087+
11088 os_snprintf(path, sizeof(path), "/proc/sys/net/ipv%d/conf/%s/%s",
11089- ip_version, bss->brname, param_txt);
11090+ ip_version, ifname, param_txt);
11091
11092 set_val:
11093 if (linux_write_system_file(path, val))
11094@@ -14019,6 +14105,8 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
11095 .set_acl = wpa_driver_nl80211_set_acl,
11096 .if_add = wpa_driver_nl80211_if_add,
11097 .if_remove = driver_nl80211_if_remove,
11098+ .if_rename = driver_nl80211_if_rename,
11099+ .set_first_bss = driver_nl80211_set_first_bss,
11100 .send_mlme = driver_nl80211_send_mlme,
11101 .get_hw_feature_data = nl80211_get_hw_feature_data,
11102 .sta_add = wpa_driver_nl80211_sta_add,
11103diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
11104index 65389d206..d6a887cef 100644
11105--- a/src/drivers/driver_nl80211_capa.c
11106+++ b/src/drivers/driver_nl80211_capa.c
11107@@ -976,6 +976,10 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
11108 nla_get_u32(tb[NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS]);
11109 }
11110
11111+ if (tb[NL80211_ATTR_MAX_SCAN_IE_LEN])
11112+ capa->max_scan_ie_len =
11113+ nla_get_u16(tb[NL80211_ATTR_MAX_SCAN_IE_LEN]);
11114+
11115 if (tb[NL80211_ATTR_MAX_MATCH_SETS])
11116 capa->max_match_sets =
11117 nla_get_u8(tb[NL80211_ATTR_MAX_MATCH_SETS]);
11118diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
11119index f5778cdaf..4a12d749c 100644
11120--- a/src/drivers/driver_nl80211_event.c
11121+++ b/src/drivers/driver_nl80211_event.c
11122@@ -1196,6 +1196,7 @@ static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
11123 struct nlattr *bw, struct nlattr *cf1,
11124 struct nlattr *cf2,
11125 struct nlattr *punct_bitmap,
11126+ struct nlattr *count,
11127 int finished)
11128 {
11129 struct i802_bss *bss;
11130@@ -1259,6 +1260,8 @@ static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
11131 data.ch_switch.cf1 = nla_get_u32(cf1);
11132 if (cf2)
11133 data.ch_switch.cf2 = nla_get_u32(cf2);
11134+ if (count)
11135+ data.ch_switch.count = nla_get_u32(count);
11136
11137 if (link)
11138 data.ch_switch.link_id = nla_get_u8(link);
11139@@ -3972,6 +3975,7 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
11140 tb[NL80211_ATTR_CENTER_FREQ1],
11141 tb[NL80211_ATTR_CENTER_FREQ2],
11142 tb[NL80211_ATTR_PUNCT_BITMAP],
11143+ tb[NL80211_ATTR_CH_SWITCH_COUNT],
11144 0);
11145 break;
11146 case NL80211_CMD_CH_SWITCH_NOTIFY:
11147@@ -3984,6 +3988,7 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
11148 tb[NL80211_ATTR_CENTER_FREQ1],
11149 tb[NL80211_ATTR_CENTER_FREQ2],
11150 tb[NL80211_ATTR_PUNCT_BITMAP],
11151+ NULL,
11152 1);
11153 break;
11154 case NL80211_CMD_DISCONNECT:
11155diff --git a/src/drivers/driver_nl80211_scan.c b/src/drivers/driver_nl80211_scan.c
11156index 577f84fef..c352a88bc 100644
11157--- a/src/drivers/driver_nl80211_scan.c
11158+++ b/src/drivers/driver_nl80211_scan.c
11159@@ -221,7 +221,7 @@ nl80211_scan_common(struct i802_bss *bss, u8 cmd,
11160 wpa_printf(MSG_DEBUG, "nl80211: Passive scan requested");
11161 }
11162
11163- if (params->extra_ies) {
11164+ if (params->extra_ies && drv->capa.max_scan_ie_len >= params->extra_ies_len) {
11165 wpa_hexdump(MSG_MSGDUMP, "nl80211: Scan extra IEs",
11166 params->extra_ies, params->extra_ies_len);
11167 if (nla_put(msg, NL80211_ATTR_IE, params->extra_ies_len,
11168diff --git a/src/drivers/drivers.c b/src/drivers/drivers.c
11169index e95df6ddb..9071da3cf 100644
11170--- a/src/drivers/drivers.c
11171+++ b/src/drivers/drivers.c
11172@@ -10,6 +10,10 @@
11173 #include "utils/common.h"
11174 #include "driver.h"
11175
11176+void (*wpa_supplicant_event)(void *ctx, enum wpa_event_type event,
11177+ union wpa_event_data *data);
11178+void (*wpa_supplicant_event_global)(void *ctx, enum wpa_event_type event,
11179+ union wpa_event_data *data);
11180
11181 const struct wpa_driver_ops *const wpa_drivers[] =
11182 {
11183diff --git a/src/drivers/drivers.mak b/src/drivers/drivers.mak
11184index a03d4a034..8da44d9f5 100644
11185--- a/src/drivers/drivers.mak
11186+++ b/src/drivers/drivers.mak
11187@@ -54,7 +54,6 @@ NEED_SME=y
11188 NEED_AP_MLME=y
11189 NEED_NETLINK=y
11190 NEED_LINUX_IOCTL=y
11191-NEED_RFKILL=y
11192 NEED_RADIOTAP=y
11193 NEED_LIBNL=y
11194 endif
11195@@ -111,7 +110,6 @@ DRV_WPA_CFLAGS += -DCONFIG_DRIVER_WEXT
11196 CONFIG_WIRELESS_EXTENSION=y
11197 NEED_NETLINK=y
11198 NEED_LINUX_IOCTL=y
11199-NEED_RFKILL=y
11200 endif
11201
11202 ifdef CONFIG_DRIVER_NDIS
11203@@ -137,7 +135,6 @@ endif
11204 ifdef CONFIG_WIRELESS_EXTENSION
11205 DRV_WPA_CFLAGS += -DCONFIG_WIRELESS_EXTENSION
11206 DRV_WPA_OBJS += ../src/drivers/driver_wext.o
11207-NEED_RFKILL=y
11208 endif
11209
11210 ifdef NEED_NETLINK
11211@@ -146,6 +143,7 @@ endif
11212
11213 ifdef NEED_RFKILL
11214 DRV_OBJS += ../src/drivers/rfkill.o
11215+DRV_WPA_CFLAGS += -DCONFIG_RFKILL
11216 endif
11217
11218 ifdef NEED_RADIOTAP
11219diff --git a/src/drivers/rfkill.h b/src/drivers/rfkill.h
11220index 0412ac330..e27565375 100644
11221--- a/src/drivers/rfkill.h
11222+++ b/src/drivers/rfkill.h
11223@@ -18,8 +18,24 @@ struct rfkill_config {
11224 void (*unblocked_cb)(void *ctx);
11225 };
11226
11227+#ifdef CONFIG_RFKILL
11228 struct rfkill_data * rfkill_init(struct rfkill_config *cfg);
11229 void rfkill_deinit(struct rfkill_data *rfkill);
11230 int rfkill_is_blocked(struct rfkill_data *rfkill);
11231+#else
11232+static inline struct rfkill_data * rfkill_init(struct rfkill_config *cfg)
11233+{
11234+ return (void *) 1;
11235+}
11236+
11237+static inline void rfkill_deinit(struct rfkill_data *rfkill)
11238+{
11239+}
11240+
11241+static inline int rfkill_is_blocked(struct rfkill_data *rfkill)
11242+{
11243+ return 0;
11244+}
11245+#endif
11246
11247 #endif /* RFKILL_H */
11248diff --git a/src/radius/radius_client.c b/src/radius/radius_client.c
11249index 2a7f36170..8e8903051 100644
11250--- a/src/radius/radius_client.c
11251+++ b/src/radius/radius_client.c
11252@@ -165,6 +165,8 @@ struct radius_client_data {
11253 */
11254 void *ctx;
11255
11256+ struct hostapd_ip_addr local_ip;
11257+
11258 /**
11259 * conf - RADIUS client configuration (list of RADIUS servers to use)
11260 */
11261@@ -818,6 +820,30 @@ static void radius_close_acct_socket(struct radius_client_data *radius)
11262 }
11263
11264
11265+/**
11266+ * radius_client_send - Get local address for the RADIUS auth socket
11267+ * @radius: RADIUS client context from radius_client_init()
11268+ * @addr: pointer to store the address
11269+ *
11270+ * This function returns the local address for the connection to the RADIUS
11271+ * auth server. It also opens the socket if it's not available yet.
11272+ */
11273+int radius_client_get_local_addr(struct radius_client_data *radius,
11274+ struct hostapd_ip_addr *addr)
11275+{
11276+ struct hostapd_radius_servers *conf = radius->conf;
11277+
11278+ if (conf->auth_server && radius->auth_sock < 0)
11279+ radius_client_init_auth(radius);
11280+
11281+ if (radius->auth_sock < 0)
11282+ return -1;
11283+
11284+ memcpy(addr, &radius->local_ip, sizeof(*addr));
11285+
11286+ return 0;
11287+}
11288+
11289 /**
11290 * radius_client_send - Send a RADIUS request
11291 * @radius: RADIUS client context from radius_client_init()
11292@@ -1711,6 +1737,10 @@ radius_change_server(struct radius_client_data *radius,
11293 wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u",
11294 inet_ntoa(claddr.sin_addr),
11295 ntohs(claddr.sin_port));
11296+ if (auth) {
11297+ radius->local_ip.af = AF_INET;
11298+ radius->local_ip.u.v4 = claddr.sin_addr;
11299+ }
11300 }
11301 break;
11302 #ifdef CONFIG_IPV6
11303@@ -1722,6 +1752,10 @@ radius_change_server(struct radius_client_data *radius,
11304 inet_ntop(AF_INET6, &claddr6.sin6_addr,
11305 abuf, sizeof(abuf)),
11306 ntohs(claddr6.sin6_port));
11307+ if (auth) {
11308+ radius->local_ip.af = AF_INET6;
11309+ radius->local_ip.u.v6 = claddr6.sin6_addr;
11310+ }
11311 }
11312 break;
11313 }
11314diff --git a/src/radius/radius_client.h b/src/radius/radius_client.h
11315index db40637ea..9a89b0382 100644
11316--- a/src/radius/radius_client.h
11317+++ b/src/radius/radius_client.h
11318@@ -274,6 +274,8 @@ int radius_client_register(struct radius_client_data *radius,
11319 void radius_client_set_interim_error_cb(struct radius_client_data *radius,
11320 void (*cb)(const u8 *addr, void *ctx),
11321 void *ctx);
11322+int radius_client_get_local_addr(struct radius_client_data *radius,
11323+ struct hostapd_ip_addr * addr);
11324 int radius_client_send(struct radius_client_data *radius,
11325 struct radius_msg *msg,
11326 RadiusType msg_type, const u8 *addr);
11327diff --git a/src/radius/radius_das.c b/src/radius/radius_das.c
11328index aaa3fc267..327782f62 100644
11329--- a/src/radius/radius_das.c
11330+++ b/src/radius/radius_das.c
11331@@ -12,13 +12,26 @@
11332 #include "utils/common.h"
11333 #include "utils/eloop.h"
11334 #include "utils/ip_addr.h"
11335+#include "utils/list.h"
11336 #include "radius.h"
11337 #include "radius_das.h"
11338
11339
11340-struct radius_das_data {
11341+static struct dl_list das_ports = DL_LIST_HEAD_INIT(das_ports);
11342+
11343+struct radius_das_port {
11344+ struct dl_list list;
11345+ struct dl_list das_data;
11346+
11347+ int port;
11348 int sock;
11349+};
11350+
11351+struct radius_das_data {
11352+ struct dl_list list;
11353+ struct radius_das_port *port;
11354 u8 *shared_secret;
11355+ u8 *nas_identifier;
11356 size_t shared_secret_len;
11357 struct hostapd_ip_addr client_addr;
11358 unsigned int time_window;
11359@@ -378,56 +391,17 @@ fail:
11360 }
11361
11362
11363-static void radius_das_receive(int sock, void *eloop_ctx, void *sock_ctx)
11364+static void
11365+radius_das_receive_msg(struct radius_das_data *das, struct radius_msg *msg,
11366+ struct sockaddr *from, socklen_t fromlen,
11367+ char *abuf, int from_port)
11368 {
11369- struct radius_das_data *das = eloop_ctx;
11370- u8 buf[1500];
11371- union {
11372- struct sockaddr_storage ss;
11373- struct sockaddr_in sin;
11374-#ifdef CONFIG_IPV6
11375- struct sockaddr_in6 sin6;
11376-#endif /* CONFIG_IPV6 */
11377- } from;
11378- char abuf[50];
11379- int from_port = 0;
11380- socklen_t fromlen;
11381- int len;
11382- struct radius_msg *msg, *reply = NULL;
11383+ struct radius_msg *reply = NULL;
11384 struct radius_hdr *hdr;
11385 struct wpabuf *rbuf;
11386+ struct os_time now;
11387 u32 val;
11388 int res;
11389- struct os_time now;
11390-
11391- fromlen = sizeof(from);
11392- len = recvfrom(sock, buf, sizeof(buf), 0,
11393- (struct sockaddr *) &from.ss, &fromlen);
11394- if (len < 0) {
11395- wpa_printf(MSG_ERROR, "DAS: recvfrom: %s", strerror(errno));
11396- return;
11397- }
11398-
11399- os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf));
11400- from_port = ntohs(from.sin.sin_port);
11401-
11402- wpa_printf(MSG_DEBUG, "DAS: Received %d bytes from %s:%d",
11403- len, abuf, from_port);
11404- if (das->client_addr.u.v4.s_addr &&
11405- das->client_addr.u.v4.s_addr != from.sin.sin_addr.s_addr) {
11406- wpa_printf(MSG_DEBUG, "DAS: Drop message from unknown client");
11407- return;
11408- }
11409-
11410- msg = radius_msg_parse(buf, len);
11411- if (msg == NULL) {
11412- wpa_printf(MSG_DEBUG, "DAS: Parsing incoming RADIUS packet "
11413- "from %s:%d failed", abuf, from_port);
11414- return;
11415- }
11416-
11417- if (wpa_debug_level <= MSG_MSGDUMP)
11418- radius_msg_dump(msg);
11419
11420 if (radius_msg_verify_das_req(msg, das->shared_secret,
11421 das->shared_secret_len,
11422@@ -494,9 +468,8 @@ static void radius_das_receive(int sock, void *eloop_ctx, void *sock_ctx)
11423 radius_msg_dump(reply);
11424
11425 rbuf = radius_msg_get_buf(reply);
11426- res = sendto(das->sock, wpabuf_head(rbuf),
11427- wpabuf_len(rbuf), 0,
11428- (struct sockaddr *) &from.ss, fromlen);
11429+ res = sendto(das->port->sock, wpabuf_head(rbuf),
11430+ wpabuf_len(rbuf), 0, from, fromlen);
11431 if (res < 0) {
11432 wpa_printf(MSG_ERROR, "DAS: sendto(to %s:%d): %s",
11433 abuf, from_port, strerror(errno));
11434@@ -508,6 +481,72 @@ fail:
11435 radius_msg_free(reply);
11436 }
11437
11438+static void radius_das_receive(int sock, void *eloop_ctx, void *sock_ctx)
11439+{
11440+ struct radius_das_port *p = eloop_ctx;
11441+ struct radius_das_data *das;
11442+ u8 buf[1500];
11443+ union {
11444+ struct sockaddr_storage ss;
11445+ struct sockaddr_in sin;
11446+#ifdef CONFIG_IPV6
11447+ struct sockaddr_in6 sin6;
11448+#endif /* CONFIG_IPV6 */
11449+ } from;
11450+ struct radius_msg *msg;
11451+ size_t nasid_len = 0;
11452+ u8 *nasid_buf = NULL;
11453+ char abuf[50];
11454+ int from_port = 0;
11455+ socklen_t fromlen;
11456+ int found = 0;
11457+ int len;
11458+
11459+ fromlen = sizeof(from);
11460+ len = recvfrom(sock, buf, sizeof(buf), 0,
11461+ (struct sockaddr *) &from.ss, &fromlen);
11462+ if (len < 0) {
11463+ wpa_printf(MSG_ERROR, "DAS: recvfrom: %s", strerror(errno));
11464+ return;
11465+ }
11466+
11467+ os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf));
11468+ from_port = ntohs(from.sin.sin_port);
11469+
11470+ msg = radius_msg_parse(buf, len);
11471+ if (msg == NULL) {
11472+ wpa_printf(MSG_DEBUG, "DAS: Parsing incoming RADIUS packet "
11473+ "from %s:%d failed", abuf, from_port);
11474+ return;
11475+ }
11476+
11477+ wpa_printf(MSG_DEBUG, "DAS: Received %d bytes from %s:%d",
11478+ len, abuf, from_port);
11479+
11480+ if (wpa_debug_level <= MSG_MSGDUMP)
11481+ radius_msg_dump(msg);
11482+
11483+ radius_msg_get_attr_ptr(msg, RADIUS_ATTR_NAS_IDENTIFIER,
11484+ &nasid_buf, &nasid_len, NULL);
11485+ dl_list_for_each(das, &p->das_data, struct radius_das_data, list) {
11486+ if (das->client_addr.u.v4.s_addr &&
11487+ das->client_addr.u.v4.s_addr != from.sin.sin_addr.s_addr)
11488+ continue;
11489+
11490+ if (das->nas_identifier && nasid_buf &&
11491+ (nasid_len != os_strlen(das->nas_identifier) ||
11492+ os_memcmp(das->nas_identifier, nasid_buf, nasid_len) != 0))
11493+ continue;
11494+
11495+ found = 1;
11496+ radius_das_receive_msg(das, msg, (struct sockaddr *)&from.ss,
11497+ fromlen, abuf, from_port);
11498+ }
11499+
11500+ if (!found)
11501+ wpa_printf(MSG_DEBUG, "DAS: Drop message from unknown client");
11502+}
11503+
11504
11505 static int radius_das_open_socket(int port)
11506 {
11507@@ -533,6 +572,49 @@ static int radius_das_open_socket(int port)
11508 }
11509
11510
11511+static struct radius_das_port *
11512+radius_das_open_port(int port)
11513+{
11514+ struct radius_das_port *p;
11515+
11516+ dl_list_for_each(p, &das_ports, struct radius_das_port, list) {
11517+ if (p->port == port)
11518+ return p;
11519+ }
11520+
11521+ p = os_zalloc(sizeof(*p));
11522+ if (p == NULL)
11523+ return NULL;
11524+
11525+ dl_list_init(&p->das_data);
11526+ p->port = port;
11527+ p->sock = radius_das_open_socket(port);
11528+ if (p->sock < 0)
11529+ goto free_port;
11530+
11531+ if (eloop_register_read_sock(p->sock, radius_das_receive, p, NULL))
11532+ goto close_port;
11533+
11534+ dl_list_add(&das_ports, &p->list);
11535+
11536+ return p;
11537+
11538+close_port:
11539+ close(p->sock);
11540+free_port:
11541+ os_free(p);
11542+
11543+ return NULL;
11544+}
11545+
11546+static void radius_das_close_port(struct radius_das_port *p)
11547+{
11548+ dl_list_del(&p->list);
11549+ eloop_unregister_read_sock(p->sock);
11550+ close(p->sock);
11551+ free(p);
11552+}
11553+
11554 struct radius_das_data *
11555 radius_das_init(struct radius_das_conf *conf)
11556 {
11557@@ -553,6 +635,8 @@ radius_das_init(struct radius_das_conf *conf)
11558 das->ctx = conf->ctx;
11559 das->disconnect = conf->disconnect;
11560 das->coa = conf->coa;
11561+ if (conf->nas_identifier)
11562+ das->nas_identifier = os_strdup(conf->nas_identifier);
11563
11564 os_memcpy(&das->client_addr, conf->client_addr,
11565 sizeof(das->client_addr));
11566@@ -565,19 +649,15 @@ radius_das_init(struct radius_das_conf *conf)
11567 }
11568 das->shared_secret_len = conf->shared_secret_len;
11569
11570- das->sock = radius_das_open_socket(conf->port);
11571- if (das->sock < 0) {
11572+ das->port = radius_das_open_port(conf->port);
11573+ if (!das->port) {
11574 wpa_printf(MSG_ERROR, "Failed to open UDP socket for RADIUS "
11575 "DAS");
11576 radius_das_deinit(das);
11577 return NULL;
11578 }
11579
11580- if (eloop_register_read_sock(das->sock, radius_das_receive, das, NULL))
11581- {
11582- radius_das_deinit(das);
11583- return NULL;
11584- }
11585+ dl_list_add(&das->port->das_data, &das->list);
11586
11587 return das;
11588 }
11589@@ -588,11 +668,14 @@ void radius_das_deinit(struct radius_das_data *das)
11590 if (das == NULL)
11591 return;
11592
11593- if (das->sock >= 0) {
11594- eloop_unregister_read_sock(das->sock);
11595- close(das->sock);
11596+ if (das->port) {
11597+ dl_list_del(&das->list);
11598+
11599+ if (dl_list_empty(&das->port->das_data))
11600+ radius_das_close_port(das->port);
11601 }
11602
11603+ os_free(das->nas_identifier);
11604 os_free(das->shared_secret);
11605 os_free(das);
11606 }
11607diff --git a/src/radius/radius_das.h b/src/radius/radius_das.h
11608index 233d662f6..80dc13fc8 100644
11609--- a/src/radius/radius_das.h
11610+++ b/src/radius/radius_das.h
11611@@ -44,6 +44,7 @@ struct radius_das_attrs {
11612 struct radius_das_conf {
11613 int port;
11614 const u8 *shared_secret;
11615+ const u8 *nas_identifier;
11616 size_t shared_secret_len;
11617 const struct hostapd_ip_addr *client_addr;
11618 unsigned int time_window;
11619diff --git a/src/radius/radius_server.c b/src/radius/radius_server.c
11620index e02c21540..57a47263e 100644
11621--- a/src/radius/radius_server.c
11622+++ b/src/radius/radius_server.c
11623@@ -63,6 +63,12 @@ struct radius_server_counters {
11624 u32 unknown_acct_types;
11625 };
11626
11627+struct radius_accept_attr {
11628+ u8 type;
11629+ u16 len;
11630+ void *data;
11631+};
11632+
11633 /**
11634 * struct radius_session - Internal RADIUS server data for a session
11635 */
11636@@ -90,7 +96,7 @@ struct radius_session {
11637 unsigned int macacl:1;
11638 unsigned int t_c_filtering:1;
11639
11640- struct hostapd_radius_attr *accept_attr;
11641+ struct radius_accept_attr *accept_attr;
11642
11643 u32 t_c_timestamp; /* Last read T&C timestamp from user DB */
11644 };
11645@@ -394,6 +400,7 @@ static void radius_server_session_free(struct radius_server_data *data,
11646 radius_msg_free(sess->last_reply);
11647 os_free(sess->username);
11648 os_free(sess->nas_ip);
11649+ os_free(sess->accept_attr);
11650 os_free(sess);
11651 data->num_sess--;
11652 }
11653@@ -554,6 +561,36 @@ radius_server_erp_find_key(struct radius_server_data *data, const char *keyname)
11654 }
11655 #endif /* CONFIG_ERP */
11656
11657+static struct radius_accept_attr *
11658+radius_server_copy_attr(const struct hostapd_radius_attr *data)
11659+{
11660+ const struct hostapd_radius_attr *attr;
11661+ struct radius_accept_attr *attr_new;
11662+ size_t data_size = 0;
11663+ void *data_buf;
11664+ int n_attr = 1;
11665+
11666+ for (attr = data; attr; attr = attr->next) {
11667+ n_attr++;
11668+ data_size += wpabuf_len(attr->val);
11669+ }
11670+
11671+ attr_new = os_zalloc(n_attr * sizeof(*attr) + data_size);
11672+ if (!attr_new)
11673+ return NULL;
11674+
11675+ data_buf = &attr_new[n_attr];
11676+ for (n_attr = 0, attr = data; attr; attr = attr->next) {
11677+ struct radius_accept_attr *cur = &attr_new[n_attr++];
11678+
11679+ cur->type = attr->type;
11680+ cur->len = wpabuf_len(attr->val);
11681+ cur->data = memcpy(data_buf, wpabuf_head(attr->val), cur->len);
11682+ data_buf += cur->len;
11683+ }
11684+
11685+ return attr_new;
11686+}
11687
11688 static struct radius_session *
11689 radius_server_get_new_session(struct radius_server_data *data,
11690@@ -607,7 +644,7 @@ radius_server_get_new_session(struct radius_server_data *data,
11691 eap_user_free(tmp);
11692 return NULL;
11693 }
11694- sess->accept_attr = tmp->accept_attr;
11695+ sess->accept_attr = radius_server_copy_attr(tmp->accept_attr);
11696 sess->macacl = tmp->macacl;
11697 eap_user_free(tmp);
11698
11699@@ -1118,11 +1155,10 @@ radius_server_encapsulate_eap(struct radius_server_data *data,
11700 }
11701
11702 if (code == RADIUS_CODE_ACCESS_ACCEPT) {
11703- struct hostapd_radius_attr *attr;
11704- for (attr = sess->accept_attr; attr; attr = attr->next) {
11705- if (!radius_msg_add_attr(msg, attr->type,
11706- wpabuf_head(attr->val),
11707- wpabuf_len(attr->val))) {
11708+ struct radius_accept_attr *attr;
11709+ for (attr = sess->accept_attr; attr->data; attr++) {
11710+ if (!radius_msg_add_attr(msg, attr->type, attr->data,
11711+ attr->len)) {
11712 wpa_printf(MSG_ERROR, "Could not add RADIUS attribute");
11713 radius_msg_free(msg);
11714 return NULL;
11715@@ -1211,11 +1247,10 @@ radius_server_macacl(struct radius_server_data *data,
11716 }
11717
11718 if (code == RADIUS_CODE_ACCESS_ACCEPT) {
11719- struct hostapd_radius_attr *attr;
11720- for (attr = sess->accept_attr; attr; attr = attr->next) {
11721- if (!radius_msg_add_attr(msg, attr->type,
11722- wpabuf_head(attr->val),
11723- wpabuf_len(attr->val))) {
11724+ struct radius_accept_attr *attr;
11725+ for (attr = sess->accept_attr; attr->data; attr++) {
11726+ if (!radius_msg_add_attr(msg, attr->type, attr->data,
11727+ attr->len)) {
11728 wpa_printf(MSG_ERROR, "Could not add RADIUS attribute");
11729 radius_msg_free(msg);
11730 return NULL;
11731@@ -2512,7 +2547,7 @@ static int radius_server_get_eap_user(void *ctx, const u8 *identity,
11732 ret = data->get_eap_user(data->conf_ctx, identity, identity_len,
11733 phase2, user);
11734 if (ret == 0 && user) {
11735- sess->accept_attr = user->accept_attr;
11736+ sess->accept_attr = radius_server_copy_attr(user->accept_attr);
11737 sess->remediation = user->remediation;
11738 sess->macacl = user->macacl;
11739 sess->t_c_timestamp = user->t_c_timestamp;
11740diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
11741index 8956c4072..e669858d8 100644
11742--- a/src/rsn_supp/wpa.c
11743+++ b/src/rsn_supp/wpa.c
11744@@ -3943,6 +3943,8 @@ static u32 wpa_key_mgmt_suite(struct wpa_sm *sm)
11745 }
11746
11747
11748+#ifdef CONFIG_CTRL_IFACE_MIB
11749+
11750 #define RSN_SUITE "%02x-%02x-%02x-%d"
11751 #define RSN_SUITE_ARG(s) \
11752 ((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff
11753@@ -4024,6 +4026,7 @@ int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen)
11754
11755 return (int) len;
11756 }
11757+#endif
11758 #endif /* CONFIG_CTRL_IFACE */
11759
11760
11761diff --git a/src/tls/Makefile b/src/tls/Makefile
11762index c84fbe859..e974a41f0 100644
11763--- a/src/tls/Makefile
11764+++ b/src/tls/Makefile
11765@@ -1,3 +1,10 @@
11766+LIB_OBJS= asn1.o
11767+
11768+ifneq ($(CONFIG_TLS),gnutls)
11769+ifneq ($(CONFIG_TLS),mbedtls)
11770+ifneq ($(CONFIG_TLS),openssl)
11771+ifneq ($(CONFIG_TLS),wolfssl)
11772+
11773 CFLAGS += -DCONFIG_INTERNAL_LIBTOMMATH
11774 CFLAGS += -DCONFIG_CRYPTO_INTERNAL
11775 CFLAGS += -DCONFIG_TLSV11
11776@@ -21,5 +28,9 @@ LIB_OBJS= \
11777 tlsv1_server_read.o \
11778 tlsv1_server_write.o \
11779 x509v3.o
11780+endif
11781+endif
11782+endif
11783+endif
11784
11785 include ../lib.rules
11786diff --git a/src/utils/eloop.c b/src/utils/eloop.c
11787index 00b0beff0..50dd1beda 100644
11788--- a/src/utils/eloop.c
11789+++ b/src/utils/eloop.c
11790@@ -77,6 +77,9 @@ struct eloop_sock_table {
11791 struct eloop_data {
11792 int max_sock;
11793
11794+ eloop_timeout_poll_handler timeout_poll_cb;
11795+ eloop_poll_handler poll_cb;
11796+
11797 size_t count; /* sum of all table counts */
11798 #ifdef CONFIG_ELOOP_POLL
11799 size_t max_pollfd_map; /* number of pollfds_map currently allocated */
11800@@ -1121,6 +1124,12 @@ void eloop_run(void)
11801 os_reltime_sub(&timeout->time, &now, &tv);
11802 else
11803 tv.sec = tv.usec = 0;
11804+ }
11805+
11806+ if (eloop.timeout_poll_cb && eloop.timeout_poll_cb(&tv, !!timeout))
11807+ timeout = (void *)1;
11808+
11809+ if (timeout) {
11810 #if defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL)
11811 timeout_ms = tv.sec * 1000 + tv.usec / 1000;
11812 #endif /* defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL) */
11813@@ -1190,7 +1199,8 @@ void eloop_run(void)
11814 eloop.exceptions.changed = 0;
11815
11816 eloop_process_pending_signals();
11817-
11818+ if (eloop.poll_cb)
11819+ eloop.poll_cb();
11820
11821 /* check if some registered timeouts have occurred */
11822 timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
11823@@ -1252,6 +1262,14 @@ out:
11824 return;
11825 }
11826
11827+int eloop_register_cb(eloop_poll_handler poll_cb,
11828+ eloop_timeout_poll_handler timeout_cb)
11829+{
11830+ eloop.poll_cb = poll_cb;
11831+ eloop.timeout_poll_cb = timeout_cb;
11832+
11833+ return 0;
11834+}
11835
11836 void eloop_terminate(void)
11837 {
11838diff --git a/src/utils/eloop.h b/src/utils/eloop.h
11839index 04ee6d183..5452ea589 100644
11840--- a/src/utils/eloop.h
11841+++ b/src/utils/eloop.h
11842@@ -65,6 +65,9 @@ typedef void (*eloop_timeout_handler)(void *eloop_ctx, void *user_ctx);
11843 */
11844 typedef void (*eloop_signal_handler)(int sig, void *signal_ctx);
11845
11846+typedef bool (*eloop_timeout_poll_handler)(struct os_reltime *tv, bool tv_set);
11847+typedef void (*eloop_poll_handler)(void);
11848+
11849 /**
11850 * eloop_init() - Initialize global event loop data
11851 * Returns: 0 on success, -1 on failure
11852@@ -73,6 +76,9 @@ typedef void (*eloop_signal_handler)(int sig, void *signal_ctx);
11853 */
11854 int eloop_init(void);
11855
11856+int eloop_register_cb(eloop_poll_handler poll_cb,
11857+ eloop_timeout_poll_handler timeout_cb);
11858+
11859 /**
11860 * eloop_register_read_sock - Register handler for read events
11861 * @sock: File descriptor number for the socket
11862@@ -320,6 +326,8 @@ int eloop_register_signal_reconfig(eloop_signal_handler handler,
11863 */
11864 int eloop_sock_requeue(void);
11865
11866+void eloop_add_uloop(void);
11867+
11868 /**
11869 * eloop_run - Start the event loop
11870 *
11871diff --git a/src/utils/uloop.c b/src/utils/uloop.c
11872new file mode 100644
11873index 000000000..c0d26db93
11874--- /dev/null
11875+++ b/src/utils/uloop.c
11876@@ -0,0 +1,64 @@
11877+#include <libubox/uloop.h>
11878+#include "includes.h"
11879+#include "common.h"
11880+#include "eloop.h"
11881+
11882+static void eloop_uloop_event_cb(int sock, void *eloop_ctx, void *sock_ctx)
11883+{
11884+}
11885+
11886+static void eloop_uloop_fd_cb(struct uloop_fd *fd, unsigned int events)
11887+{
11888+ unsigned int changed = events ^ fd->flags;
11889+
11890+ if (changed & ULOOP_READ) {
11891+ if (events & ULOOP_READ)
11892+ eloop_register_sock(fd->fd, EVENT_TYPE_READ, eloop_uloop_event_cb, fd, fd);
11893+ else
11894+ eloop_unregister_sock(fd->fd, EVENT_TYPE_READ);
11895+ }
11896+
11897+ if (changed & ULOOP_WRITE) {
11898+ if (events & ULOOP_WRITE)
11899+ eloop_register_sock(fd->fd, EVENT_TYPE_WRITE, eloop_uloop_event_cb, fd, fd);
11900+ else
11901+ eloop_unregister_sock(fd->fd, EVENT_TYPE_WRITE);
11902+ }
11903+}
11904+
11905+static bool uloop_timeout_poll_handler(struct os_reltime *tv, bool tv_set)
11906+{
11907+ struct os_reltime tv_uloop;
11908+ int timeout_ms = uloop_get_next_timeout();
11909+
11910+ if (timeout_ms < 0)
11911+ return false;
11912+
11913+ tv_uloop.sec = timeout_ms / 1000;
11914+ tv_uloop.usec = (timeout_ms % 1000) * 1000;
11915+
11916+ if (!tv_set || os_reltime_before(&tv_uloop, tv)) {
11917+ *tv = tv_uloop;
11918+ return true;
11919+ }
11920+
11921+ return false;
11922+}
11923+
11924+static void uloop_poll_handler(void)
11925+{
11926+ uloop_run_timeout(0);
11927+}
11928+
11929+void eloop_add_uloop(void)
11930+{
11931+ static bool init_done = false;
11932+
11933+ if (!init_done) {
11934+ uloop_init();
11935+ uloop_fd_set_cb = eloop_uloop_fd_cb;
11936+ init_done = true;
11937+ }
11938+
11939+ eloop_register_cb(uloop_poll_handler, uloop_timeout_poll_handler);
11940+}
11941diff --git a/src/utils/wpa_debug.c b/src/utils/wpa_debug.c
11942index 7f3dd185f..627575e39 100644
11943--- a/src/utils/wpa_debug.c
11944+++ b/src/utils/wpa_debug.c
11945@@ -26,6 +26,10 @@ static FILE *wpa_debug_tracing_file = NULL;
11946 #define WPAS_TRACE_PFX "wpas <%d>: "
11947 #endif /* CONFIG_DEBUG_LINUX_TRACING */
11948
11949+void (*wpa_printf_hook)(int level, const char *fmt, va_list ap);
11950+void (*wpa_hexdump_hook)(int level, const char *title, const void *buf,
11951+ size_t len);
11952+void (*wpa_netlink_hook)(int tx, const void *data, size_t len);
11953
11954 int wpa_debug_level = MSG_INFO;
11955 int wpa_debug_show_keys = 0;
11956@@ -206,10 +210,16 @@ void wpa_debug_close_linux_tracing(void)
11957 *
11958 * Note: New line '\n' is added to the end of the text when printing to stdout.
11959 */
11960-void wpa_printf(int level, const char *fmt, ...)
11961+void _wpa_printf(int level, const char *fmt, ...)
11962 {
11963 va_list ap;
11964
11965+ if (wpa_printf_hook) {
11966+ va_start(ap, fmt);
11967+ wpa_printf_hook(level, fmt, ap);
11968+ va_end(ap);
11969+ }
11970+
11971 if (level >= wpa_debug_level) {
11972 #ifdef CONFIG_ANDROID_LOG
11973 va_start(ap, fmt);
11974@@ -255,11 +265,14 @@ void wpa_printf(int level, const char *fmt, ...)
11975 }
11976
11977
11978-static void _wpa_hexdump(int level, const char *title, const u8 *buf,
11979+void _wpa_hexdump(int level, const char *title, const u8 *buf,
11980 size_t len, int show, int only_syslog)
11981 {
11982 size_t i;
11983
11984+ if (wpa_hexdump_hook)
11985+ wpa_hexdump_hook(level, title, buf, len);
11986+
11987 #ifdef CONFIG_DEBUG_LINUX_TRACING
11988 if (wpa_debug_tracing_file != NULL) {
11989 fprintf(wpa_debug_tracing_file,
11990@@ -382,19 +395,7 @@ static void _wpa_hexdump(int level, const char *title, const u8 *buf,
11991 #endif /* CONFIG_ANDROID_LOG */
11992 }
11993
11994-void wpa_hexdump(int level, const char *title, const void *buf, size_t len)
11995-{
11996- _wpa_hexdump(level, title, buf, len, 1, 0);
11997-}
11998-
11999-
12000-void wpa_hexdump_key(int level, const char *title, const void *buf, size_t len)
12001-{
12002- _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys, 0);
12003-}
12004-
12005-
12006-static void _wpa_hexdump_ascii(int level, const char *title, const void *buf,
12007+void _wpa_hexdump_ascii(int level, const char *title, const void *buf,
12008 size_t len, int show)
12009 {
12010 size_t i, llen;
12011@@ -507,20 +508,6 @@ file_done:
12012 }
12013
12014
12015-void wpa_hexdump_ascii(int level, const char *title, const void *buf,
12016- size_t len)
12017-{
12018- _wpa_hexdump_ascii(level, title, buf, len, 1);
12019-}
12020-
12021-
12022-void wpa_hexdump_ascii_key(int level, const char *title, const void *buf,
12023- size_t len)
12024-{
12025- _wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys);
12026-}
12027-
12028-
12029 #ifdef CONFIG_DEBUG_FILE
12030 static char *last_path = NULL;
12031 #endif /* CONFIG_DEBUG_FILE */
12032@@ -644,7 +631,7 @@ void wpa_msg_register_ifname_cb(wpa_msg_get_ifname_func func)
12033 }
12034
12035
12036-void wpa_msg(void *ctx, int level, const char *fmt, ...)
12037+void _wpa_msg(void *ctx, int level, const char *fmt, ...)
12038 {
12039 va_list ap;
12040 char *buf;
12041@@ -682,7 +669,7 @@ void wpa_msg(void *ctx, int level, const char *fmt, ...)
12042 }
12043
12044
12045-void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...)
12046+void _wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...)
12047 {
12048 va_list ap;
12049 char *buf;
12050diff --git a/src/utils/wpa_debug.h b/src/utils/wpa_debug.h
12051index 4c02ad3c7..854520bfe 100644
12052--- a/src/utils/wpa_debug.h
12053+++ b/src/utils/wpa_debug.h
12054@@ -11,6 +11,10 @@
12055
12056 #include "wpabuf.h"
12057
12058+extern void (*wpa_printf_hook)(int level, const char *fmt, va_list ap);
12059+extern void (*wpa_hexdump_hook)(int level, const char *title,
12060+ const void *buf, size_t len);
12061+extern void (*wpa_netlink_hook)(int tx, const void *data, size_t len);
12062 extern int wpa_debug_level;
12063 extern int wpa_debug_show_keys;
12064 extern int wpa_debug_timestamp;
12065@@ -51,6 +55,17 @@ void wpa_debug_close_file(void);
12066 void wpa_debug_setup_stdout(void);
12067 void wpa_debug_stop_log(void);
12068
12069+/* internal */
12070+void _wpa_hexdump(int level, const char *title, const u8 *buf,
12071+ size_t len, int show, int only_syslog);
12072+void _wpa_hexdump_ascii(int level, const char *title, const void *buf,
12073+ size_t len, int show);
12074+extern int wpa_debug_show_keys;
12075+
12076+#ifndef CONFIG_MSG_MIN_PRIORITY
12077+#define CONFIG_MSG_MIN_PRIORITY 0
12078+#endif
12079+
12080 /**
12081 * wpa_debug_printf_timestamp - Print timestamp for debug output
12082 *
12083@@ -71,9 +86,15 @@ void wpa_debug_print_timestamp(void);
12084 *
12085 * Note: New line '\n' is added to the end of the text when printing to stdout.
12086 */
12087-void wpa_printf(int level, const char *fmt, ...)
12088+void _wpa_printf(int level, const char *fmt, ...)
12089 PRINTF_FORMAT(2, 3);
12090
12091+#define wpa_printf(level, ...) \
12092+ do { \
12093+ if (level >= CONFIG_MSG_MIN_PRIORITY) \
12094+ _wpa_printf(level, __VA_ARGS__); \
12095+ } while(0)
12096+
12097 /**
12098 * wpa_hexdump - conditional hex dump
12099 * @level: priority level (MSG_*) of the message
12100@@ -85,7 +106,13 @@ PRINTF_FORMAT(2, 3);
12101 * output may be directed to stdout, stderr, and/or syslog based on
12102 * configuration. The contents of buf is printed out has hex dump.
12103 */
12104-void wpa_hexdump(int level, const char *title, const void *buf, size_t len);
12105+static inline void wpa_hexdump(int level, const char *title, const void *buf, size_t len)
12106+{
12107+ if (level < CONFIG_MSG_MIN_PRIORITY)
12108+ return;
12109+
12110+ _wpa_hexdump(level, title, buf, len, 1, 1);
12111+}
12112
12113 static inline void wpa_hexdump_buf(int level, const char *title,
12114 const struct wpabuf *buf)
12115@@ -107,7 +134,13 @@ static inline void wpa_hexdump_buf(int level, const char *title,
12116 * like wpa_hexdump(), but by default, does not include secret keys (passwords,
12117 * etc.) in debug output.
12118 */
12119-void wpa_hexdump_key(int level, const char *title, const void *buf, size_t len);
12120+static inline void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len)
12121+{
12122+ if (level < CONFIG_MSG_MIN_PRIORITY)
12123+ return;
12124+
12125+ _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys, 1);
12126+}
12127
12128 static inline void wpa_hexdump_buf_key(int level, const char *title,
12129 const struct wpabuf *buf)
12130@@ -129,8 +162,14 @@ static inline void wpa_hexdump_buf_key(int level, const char *title,
12131 * the hex numbers and ASCII characters (for printable range) are shown. 16
12132 * bytes per line will be shown.
12133 */
12134-void wpa_hexdump_ascii(int level, const char *title, const void *buf,
12135- size_t len);
12136+static inline void wpa_hexdump_ascii(int level, const char *title,
12137+ const u8 *buf, size_t len)
12138+{
12139+ if (level < CONFIG_MSG_MIN_PRIORITY)
12140+ return;
12141+
12142+ _wpa_hexdump_ascii(level, title, buf, len, 1);
12143+}
12144
12145 /**
12146 * wpa_hexdump_ascii_key - conditional hex dump, hide keys
12147@@ -146,8 +185,14 @@ void wpa_hexdump_ascii(int level, const char *title, const void *buf,
12148 * bytes per line will be shown. This works like wpa_hexdump_ascii(), but by
12149 * default, does not include secret keys (passwords, etc.) in debug output.
12150 */
12151-void wpa_hexdump_ascii_key(int level, const char *title, const void *buf,
12152- size_t len);
12153+static inline void wpa_hexdump_ascii_key(int level, const char *title,
12154+ const u8 *buf, size_t len)
12155+{
12156+ if (level < CONFIG_MSG_MIN_PRIORITY)
12157+ return;
12158+
12159+ _wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys);
12160+}
12161
12162 /*
12163 * wpa_dbg() behaves like wpa_msg(), but it can be removed from build to reduce
12164@@ -184,7 +229,12 @@ void wpa_hexdump_ascii_key(int level, const char *title, const void *buf,
12165 *
12166 * Note: New line '\n' is added to the end of the text when printing to stdout.
12167 */
12168-void wpa_msg(void *ctx, int level, const char *fmt, ...) PRINTF_FORMAT(3, 4);
12169+void _wpa_msg(void *ctx, int level, const char *fmt, ...) PRINTF_FORMAT(3, 4);
12170+#define wpa_msg(ctx, level, ...) \
12171+ do { \
12172+ if (level >= CONFIG_MSG_MIN_PRIORITY) \
12173+ _wpa_msg(ctx, level, __VA_ARGS__); \
12174+ } while(0)
12175
12176 /**
12177 * wpa_msg_ctrl - Conditional printf for ctrl_iface monitors
12178@@ -198,8 +248,13 @@ void wpa_msg(void *ctx, int level, const char *fmt, ...) PRINTF_FORMAT(3, 4);
12179 * attached ctrl_iface monitors. In other words, it can be used for frequent
12180 * events that do not need to be sent to syslog.
12181 */
12182-void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...)
12183+void _wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...)
12184 PRINTF_FORMAT(3, 4);
12185+#define wpa_msg_ctrl(ctx, level, ...) \
12186+ do { \
12187+ if (level >= CONFIG_MSG_MIN_PRIORITY) \
12188+ _wpa_msg_ctrl(ctx, level, __VA_ARGS__); \
12189+ } while(0)
12190
12191 /**
12192 * wpa_msg_global - Global printf for ctrl_iface monitors
12193diff --git a/tests/Makefile b/tests/Makefile
12194index 8ec154bb3..58287f56f 100644
12195--- a/tests/Makefile
12196+++ b/tests/Makefile
12197@@ -5,6 +5,14 @@ ALL=test-base64 test-md4 test-milenage \
12198 test-sha256 test-aes test-x509v3 test-list test-rc4 \
12199 test-bss
12200
12201+RUN_TESTS= \
12202+ test-list \
12203+ test-md4 test-rc4 test-sha1 test-sha256 \
12204+ test-milenage test-aes \
12205+ test-crypto_module
12206+
12207+ALL=$(RUN_TESTS) test-base64 test-https test-https_server
12208+
12209 include ../src/build.rules
12210
12211 ifdef LIBFUZZER
12212@@ -25,13 +33,27 @@ CFLAGS += -DCONFIG_IEEE80211R_AP
12213 CFLAGS += -DCONFIG_IEEE80211R
12214 CFLAGS += -DCONFIG_TDLS
12215
12216+# test-crypto_module
12217+CFLAGS += -DCONFIG_MODULE_TESTS
12218+CFLAGS += -DCONFIG_DPP
12219+#CFLAGS += -DCONFIG_DPP2
12220+#CFLAGS += -DCONFIG_DPP3
12221+CFLAGS += -DCONFIG_ECC
12222+CFLAGS += -DCONFIG_HMAC_SHA256_KDF
12223+CFLAGS += -DCONFIG_HMAC_SHA384_KDF
12224+CFLAGS += -DCONFIG_MESH
12225+CFLAGS += -DCONFIG_SHA256
12226+CFLAGS += -DCONFIG_SHA384
12227+CFLAGS += -DEAP_PSK
12228+CFLAGS += -DEAP_FAST
12229+
12230 CFLAGS += -I../src
12231 CFLAGS += -I../src/utils
12232
12233 SLIBS = ../src/utils/libutils.a
12234
12235-DLIBS = ../src/crypto/libcrypto.a \
12236- ../src/tls/libtls.a
12237+DLIBS = ../src/tls/libtls.a \
12238+ ../src/crypto/libcrypto.a
12239
12240 _OBJS_VAR := LLIBS
12241 include ../src/objs.mk
12242@@ -43,12 +65,43 @@ include ../src/objs.mk
12243 LIBS = $(SLIBS) $(DLIBS)
12244 LLIBS = -Wl,--start-group $(DLIBS) -Wl,--end-group $(SLIBS)
12245
12246+ifeq ($(CONFIG_TLS),mbedtls)
12247+CFLAGS += -DCONFIG_TLS_MBEDTLS
12248+LLIBS += -lmbedtls -lmbedx509 -lmbedcrypto
12249+else
12250+ifeq ($(CONFIG_TLS),openssl)
12251+CFLAGS += -DCONFIG_TLS_OPENSSL
12252+LLIBS += -lssl -lcrypto
12253+else
12254+ifeq ($(CONFIG_TLS),gnutls)
12255+CFLAGS += -DCONFIG_TLS_GNUTLS
12256+LLIBS += -lgnutls -lgpg-error -lgcrypt
12257+else
12258+ifeq ($(CONFIG_TLS),wolfssl)
12259+CFLAGS += -DCONFIG_TLS_WOLFSSL
12260+LLIBS += -lwolfssl -lm
12261+else
12262+CFLAGS += -DCONFIG_TLS_INTERNAL
12263+CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER
12264+ALL += test-rsa-sig-ver
12265+ALL += test-x509v3
12266+clean-config_tls_internal:
12267+ rm -f test_x509v3_nist.out.*
12268+ rm -f test_x509v3_nist2.out.*
12269+endif
12270+endif
12271+endif
12272+endif
12273+
12274 # glibc < 2.17 needs -lrt for clock_gettime()
12275 LLIBS += -lrt
12276
12277 test-aes: $(call BUILDOBJ,test-aes.o) $(LIBS)
12278 $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS)
12279
12280+test-crypto_module: $(call BUILDOBJ,test-crypto_module.o) $(LIBS)
12281+ $(LDO) $(LDFLAGS) -o $@ $< $(LLIBS)
12282+
12283 test-base64: $(call BUILDOBJ,test-base64.o) $(LIBS)
12284 $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS)
12285
12286@@ -149,10 +202,12 @@ run-tests: $(ALL)
12287 ./test-sha1
12288 ./test-sha256
12289 ./test-bss
12290+
12291+ @set -ex; for i in $(RUN_TESTS); do ./$$i; done
12292 @echo
12293 @echo All tests completed successfully.
12294
12295-clean: common-clean
12296+clean: common-clean clean-config_tls_internal
12297 rm -f *~
12298- rm -f test_x509v3_nist.out.*
12299- rm -f test_x509v3_nist2.out.*
12300+
12301+.PHONY: run-tests clean-config_tls_internal
12302diff --git a/tests/hwsim/example-hostapd.config b/tests/hwsim/example-hostapd.config
12303index 210b7fb86..608e20eed 100644
12304--- a/tests/hwsim/example-hostapd.config
12305+++ b/tests/hwsim/example-hostapd.config
12306@@ -4,6 +4,7 @@ CONFIG_DRIVER_NONE=y
12307 CONFIG_DRIVER_NL80211=y
12308 CONFIG_RSN_PREAUTH=y
12309
12310+#CONFIG_TLS=mbedtls
12311 #CONFIG_TLS=internal
12312 #CONFIG_INTERNAL_LIBTOMMATH=y
12313 #CONFIG_INTERNAL_LIBTOMMATH_FAST=y
12314@@ -33,12 +34,7 @@ CONFIG_EAP_TNC=y
12315 CFLAGS += -DTNC_CONFIG_FILE=\"tnc/tnc_config\"
12316 LIBS += -rdynamic
12317 CONFIG_EAP_UNAUTH_TLS=y
12318-ifeq ($(CONFIG_TLS), openssl)
12319-CONFIG_EAP_PWD=y
12320-endif
12321-ifeq ($(CONFIG_TLS), wolfssl)
12322-CONFIG_EAP_PWD=y
12323-endif
12324+CONFIG_EAP_PWD=$(if $(filter openssl wolfssl mbedtls,$(CONFIG_TLS)),y,)
12325 CONFIG_EAP_EKE=y
12326 CONFIG_PKCS12=y
12327 CONFIG_RADIUS_SERVER=y
12328@@ -88,7 +84,7 @@ CFLAGS += -DCONFIG_RADIUS_TEST
12329 CONFIG_MODULE_TESTS=y
12330
12331 CONFIG_SUITEB=y
12332-CONFIG_SUITEB192=y
12333+CONFIG_SUITEB192=$(if $(filter openssl mbedtls,$(CONFIG_TLS)),y,)
12334
12335 # AddressSanitizer (ASan) can be enabled by uncommenting the following lines.
12336 # This can be used as a more efficient memory error detector than valgrind
12337diff --git a/tests/hwsim/example-wpa_supplicant.config b/tests/hwsim/example-wpa_supplicant.config
12338index 123f397e3..da0dde659 100644
12339--- a/tests/hwsim/example-wpa_supplicant.config
12340+++ b/tests/hwsim/example-wpa_supplicant.config
12341@@ -2,6 +2,7 @@
12342
12343 CONFIG_TLS=openssl
12344 #CONFIG_TLS=wolfssl
12345+#CONFIG_TLS=mbedtls
12346 #CONFIG_TLS=internal
12347 #CONFIG_INTERNAL_LIBTOMMATH=y
12348 #CONFIG_INTERNAL_LIBTOMMATH_FAST=y
12349@@ -34,13 +35,7 @@ LIBS += -rdynamic
12350 CONFIG_EAP_FAST=y
12351 CONFIG_EAP_TEAP=y
12352 CONFIG_EAP_IKEV2=y
12353-
12354-ifeq ($(CONFIG_TLS), openssl)
12355-CONFIG_EAP_PWD=y
12356-endif
12357-ifeq ($(CONFIG_TLS), wolfssl)
12358-CONFIG_EAP_PWD=y
12359-endif
12360+CONFIG_EAP_PWD=$(if $(filter openssl wolfssl mbedtls,$(CONFIG_TLS)),y,)
12361
12362 CONFIG_USIM_SIMULATOR=y
12363 CONFIG_SIM_SIMULATOR=y
12364@@ -136,7 +131,7 @@ CONFIG_TESTING_OPTIONS=y
12365 CONFIG_MODULE_TESTS=y
12366
12367 CONFIG_SUITEB=y
12368-CONFIG_SUITEB192=y
12369+CONFIG_SUITEB192=$(if $(filter openssl mbedtls,$(CONFIG_TLS)),y,)
12370
12371 # AddressSanitizer (ASan) can be enabled by uncommenting the following lines.
12372 # This can be used as a more efficient memory error detector than valgrind
12373diff --git a/tests/hwsim/test_ap_eap.py b/tests/hwsim/test_ap_eap.py
12374index a20140316..027a60b25 100644
12375--- a/tests/hwsim/test_ap_eap.py
12376+++ b/tests/hwsim/test_ap_eap.py
12377@@ -42,20 +42,42 @@ def check_eap_capa(dev, method):
12378 res = dev.get_capability("eap")
12379 if method not in res:
12380 raise HwsimSkip("EAP method %s not supported in the build" % method)
12381+ if method == "FAST" or method == "TEAP":
12382+ tls = dev.request("GET tls_library")
12383+ if tls.startswith("mbed TLS"):
12384+ raise HwsimSkip("EAP-%s not supported with this TLS library: " % method + tls)
12385
12386 def check_subject_match_support(dev):
12387 tls = dev.request("GET tls_library")
12388- if not tls.startswith("OpenSSL") and not tls.startswith("wolfSSL"):
12389+ if tls.startswith("OpenSSL"):
12390+ return
12391+ elif tls.startswith("wolfSSL"):
12392+ return
12393+ elif tls.startswith("mbed TLS"):
12394+ return
12395+ else:
12396 raise HwsimSkip("subject_match not supported with this TLS library: " + tls)
12397
12398 def check_check_cert_subject_support(dev):
12399 tls = dev.request("GET tls_library")
12400- if not tls.startswith("OpenSSL") and not tls.startswith("wolfSSL"):
12401+ if tls.startswith("OpenSSL"):
12402+ return
12403+ elif tls.startswith("wolfSSL"):
12404+ return
12405+ elif tls.startswith("mbed TLS"):
12406+ return
12407+ else:
12408 raise HwsimSkip("check_cert_subject not supported with this TLS library: " + tls)
12409
12410 def check_altsubject_match_support(dev):
12411 tls = dev.request("GET tls_library")
12412- if not tls.startswith("OpenSSL") and not tls.startswith("wolfSSL"):
12413+ if tls.startswith("OpenSSL"):
12414+ return
12415+ elif tls.startswith("wolfSSL"):
12416+ return
12417+ elif tls.startswith("mbed TLS"):
12418+ return
12419+ else:
12420 raise HwsimSkip("altsubject_match not supported with this TLS library: " + tls)
12421
12422 def check_domain_match(dev):
12423@@ -70,7 +92,13 @@ def check_domain_suffix_match(dev):
12424
12425 def check_domain_match_full(dev):
12426 tls = dev.request("GET tls_library")
12427- if not tls.startswith("OpenSSL") and not tls.startswith("wolfSSL"):
12428+ if tls.startswith("OpenSSL"):
12429+ return
12430+ elif tls.startswith("wolfSSL"):
12431+ return
12432+ elif tls.startswith("mbed TLS"):
12433+ return
12434+ else:
12435 raise HwsimSkip("domain_suffix_match requires full match with this TLS library: " + tls)
12436
12437 def check_cert_probe_support(dev):
12438@@ -79,8 +107,15 @@ def check_cert_probe_support(dev):
12439 raise HwsimSkip("Certificate probing not supported with this TLS library: " + tls)
12440
12441 def check_ext_cert_check_support(dev):
12442+ if not openssl_imported:
12443+ raise HwsimSkip("OpenSSL python method not available")
12444+
12445 tls = dev.request("GET tls_library")
12446- if not tls.startswith("OpenSSL"):
12447+ if tls.startswith("OpenSSL"):
12448+ return
12449+ elif tls.startswith("mbed TLS"):
12450+ return
12451+ else:
12452 raise HwsimSkip("ext_cert_check not supported with this TLS library: " + tls)
12453
12454 def check_ocsp_support(dev):
12455@@ -91,10 +126,12 @@ def check_ocsp_support(dev):
12456 # raise HwsimSkip("OCSP not supported with this TLS library: " + tls)
12457 #if tls.startswith("wolfSSL"):
12458 # raise HwsimSkip("OCSP not supported with this TLS library: " + tls)
12459+ if tls.startswith("mbed TLS"):
12460+ raise HwsimSkip("OCSP not supported with this TLS library: " + tls)
12461
12462 def check_pkcs5_v15_support(dev):
12463 tls = dev.request("GET tls_library")
12464- if "BoringSSL" in tls or "GnuTLS" in tls:
12465+ if "BoringSSL" in tls or "GnuTLS" in tls or "mbed TLS" in tls:
12466 raise HwsimSkip("PKCS#5 v1.5 not supported with this TLS library: " + tls)
12467
12468 def check_tls13_support(dev):
12469@@ -122,11 +159,15 @@ def check_pkcs12_support(dev):
12470 # raise HwsimSkip("PKCS#12 not supported with this TLS library: " + tls)
12471 if tls.startswith("wolfSSL"):
12472 raise HwsimSkip("PKCS#12 not supported with this TLS library: " + tls)
12473+ if tls.startswith("mbed TLS"):
12474+ raise HwsimSkip("PKCS#12 not supported with this TLS library: " + tls)
12475
12476 def check_dh_dsa_support(dev):
12477 tls = dev.request("GET tls_library")
12478 if tls.startswith("internal"):
12479 raise HwsimSkip("DH DSA not supported with this TLS library: " + tls)
12480+ if tls.startswith("mbed TLS"):
12481+ raise HwsimSkip("DH DSA not supported with this TLS library: " + tls)
12482
12483 def check_ec_support(dev):
12484 tls = dev.request("GET tls_library")
12485@@ -1741,7 +1782,7 @@ def test_ap_wpa2_eap_ttls_pap_subject_match(dev, apdev):
12486 eap_connect(dev[0], hapd, "TTLS", "pap user",
12487 anonymous_identity="ttls", password="password",
12488 ca_cert="auth_serv/ca.pem", phase2="auth=PAP",
12489- subject_match="/C=FI/O=w1.fi/CN=server.w1.fi",
12490+ check_cert_subject="/C=FI/O=w1.fi/CN=server.w1.fi",
12491 altsubject_match="EMAIL:noone@example.com;DNS:server.w1.fi;URI:http://example.com/")
12492 eap_reauth(dev[0], "TTLS")
12493
12494@@ -2976,6 +3017,7 @@ def test_ap_wpa2_eap_tls_neg_domain_match(dev, apdev):
12495
12496 def test_ap_wpa2_eap_tls_neg_subject_match(dev, apdev):
12497 """WPA2-Enterprise negative test - subject mismatch"""
12498+ check_subject_match_support(dev[0])
12499 params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
12500 hostapd.add_ap(apdev[0], params)
12501 dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
12502@@ -3036,6 +3078,7 @@ def test_ap_wpa2_eap_tls_neg_subject_match(dev, apdev):
12503
12504 def test_ap_wpa2_eap_tls_neg_altsubject_match(dev, apdev):
12505 """WPA2-Enterprise negative test - altsubject mismatch"""
12506+ check_altsubject_match_support(dev[0])
12507 params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
12508 hostapd.add_ap(apdev[0], params)
12509
12510@@ -3582,7 +3625,7 @@ def test_ap_wpa2_eap_ikev2_oom(dev, apdev):
12511 dev[0].request("REMOVE_NETWORK all")
12512
12513 tls = dev[0].request("GET tls_library")
12514- if not tls.startswith("wolfSSL"):
12515+ if not tls.startswith("wolfSSL") and not tls.startswith("mbed TLS"):
12516 tests = [(1, "os_get_random;dh_init")]
12517 else:
12518 tests = [(1, "crypto_dh_init;dh_init")]
12519@@ -4896,7 +4939,7 @@ def test_ap_wpa2_eap_tls_intermediate_ca(dev, apdev, params):
12520 params["private_key"] = "auth_serv/iCA-server/server.key"
12521 hostapd.add_ap(apdev[0], params)
12522 tls = dev[0].request("GET tls_library")
12523- if "GnuTLS" in tls or "wolfSSL" in tls:
12524+ if "GnuTLS" in tls or "wolfSSL" in tls or "mbed TLS" in tls:
12525 ca_cert = "auth_serv/iCA-user/ca-and-root.pem"
12526 client_cert = "auth_serv/iCA-user/user_and_ica.pem"
12527 else:
12528@@ -4962,6 +5005,7 @@ def test_ap_wpa2_eap_tls_intermediate_ca_ocsp_sha1(dev, apdev, params):
12529 run_ap_wpa2_eap_tls_intermediate_ca_ocsp(dev, apdev, params, "-sha1")
12530
12531 def run_ap_wpa2_eap_tls_intermediate_ca_ocsp(dev, apdev, params, md):
12532+ check_ocsp_support(dev[0])
12533 params = int_eap_server_params()
12534 params["ca_cert"] = "auth_serv/iCA-server/ca-and-root.pem"
12535 params["server_cert"] = "auth_serv/iCA-server/server.pem"
12536@@ -4971,7 +5015,7 @@ def run_ap_wpa2_eap_tls_intermediate_ca_ocsp(dev, apdev, params, md):
12537 try:
12538 hostapd.add_ap(apdev[0], params)
12539 tls = dev[0].request("GET tls_library")
12540- if "GnuTLS" in tls or "wolfSSL" in tls:
12541+ if "GnuTLS" in tls or "wolfSSL" in tls or "mbed TLS" in tls:
12542 ca_cert = "auth_serv/iCA-user/ca-and-root.pem"
12543 client_cert = "auth_serv/iCA-user/user_and_ica.pem"
12544 else:
12545@@ -5007,7 +5051,7 @@ def run_ap_wpa2_eap_tls_intermediate_ca_ocsp_revoked(dev, apdev, params, md):
12546 try:
12547 hostapd.add_ap(apdev[0], params)
12548 tls = dev[0].request("GET tls_library")
12549- if "GnuTLS" in tls or "wolfSSL" in tls:
12550+ if "GnuTLS" in tls or "wolfSSL" in tls or "mbed TLS" in tls:
12551 ca_cert = "auth_serv/iCA-user/ca-and-root.pem"
12552 client_cert = "auth_serv/iCA-user/user_and_ica.pem"
12553 else:
12554@@ -5057,7 +5101,7 @@ def test_ap_wpa2_eap_tls_intermediate_ca_ocsp_multi_missing_resp(dev, apdev, par
12555 try:
12556 hostapd.add_ap(apdev[0], params)
12557 tls = dev[0].request("GET tls_library")
12558- if "GnuTLS" in tls or "wolfSSL" in tls:
12559+ if "GnuTLS" in tls or "wolfSSL" in tls or "mbed TLS" in tls:
12560 ca_cert = "auth_serv/iCA-user/ca-and-root.pem"
12561 client_cert = "auth_serv/iCA-user/user_and_ica.pem"
12562 else:
12563@@ -5124,7 +5168,7 @@ def test_ap_wpa2_eap_tls_intermediate_ca_ocsp_multi(dev, apdev, params):
12564
12565 hostapd.add_ap(apdev[0], params)
12566 tls = dev[0].request("GET tls_library")
12567- if "GnuTLS" in tls or "wolfSSL" in tls:
12568+ if "GnuTLS" in tls or "wolfSSL" in tls or "mbed TLS" in tls:
12569 ca_cert = "auth_serv/iCA-user/ca-and-root.pem"
12570 client_cert = "auth_serv/iCA-user/user_and_ica.pem"
12571 else:
12572@@ -5382,6 +5426,7 @@ def test_ap_wpa2_eap_ttls_server_cert_eku_client_server(dev, apdev):
12573
12574 def test_ap_wpa2_eap_ttls_server_pkcs12(dev, apdev):
12575 """WPA2-Enterprise using EAP-TTLS and server PKCS#12 file"""
12576+ check_pkcs12_support(dev[0])
12577 skip_with_fips(dev[0])
12578 params = int_eap_server_params()
12579 del params["server_cert"]
12580@@ -5394,6 +5439,7 @@ def test_ap_wpa2_eap_ttls_server_pkcs12(dev, apdev):
12581
12582 def test_ap_wpa2_eap_ttls_server_pkcs12_extra(dev, apdev):
12583 """EAP-TTLS and server PKCS#12 file with extra certs"""
12584+ check_pkcs12_support(dev[0])
12585 skip_with_fips(dev[0])
12586 params = int_eap_server_params()
12587 del params["server_cert"]
12588@@ -5416,6 +5462,7 @@ def test_ap_wpa2_eap_ttls_dh_params_server(dev, apdev):
12589
12590 def test_ap_wpa2_eap_ttls_dh_params_dsa_server(dev, apdev):
12591 """WPA2-Enterprise using EAP-TTLS and alternative server dhparams (DSA)"""
12592+ check_dh_dsa_support(dev[0])
12593 params = int_eap_server_params()
12594 params["dh_file"] = "auth_serv/dsaparam.pem"
12595 hapd = hostapd.add_ap(apdev[0], params)
12596@@ -5727,8 +5774,8 @@ def test_ap_wpa2_eap_non_ascii_identity2(dev, apdev):
12597 def test_openssl_cipher_suite_config_wpas(dev, apdev):
12598 """OpenSSL cipher suite configuration on wpa_supplicant"""
12599 tls = dev[0].request("GET tls_library")
12600- if not tls.startswith("OpenSSL"):
12601- raise HwsimSkip("TLS library is not OpenSSL: " + tls)
12602+ if not tls.startswith("OpenSSL") and not tls.startswith("mbed TLS"):
12603+ raise HwsimSkip("TLS library is not OpenSSL or mbed TLS: " + tls)
12604 params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
12605 hapd = hostapd.add_ap(apdev[0], params)
12606 eap_connect(dev[0], hapd, "TTLS", "pap user",
12607@@ -5754,14 +5801,14 @@ def test_openssl_cipher_suite_config_wpas(dev, apdev):
12608 def test_openssl_cipher_suite_config_hapd(dev, apdev):
12609 """OpenSSL cipher suite configuration on hostapd"""
12610 tls = dev[0].request("GET tls_library")
12611- if not tls.startswith("OpenSSL"):
12612- raise HwsimSkip("wpa_supplicant TLS library is not OpenSSL: " + tls)
12613+ if not tls.startswith("OpenSSL") and not tls.startswith("mbed TLS"):
12614+ raise HwsimSkip("wpa_supplicant TLS library is not OpenSSL or mbed TLS: " + tls)
12615 params = int_eap_server_params()
12616 params['openssl_ciphers'] = "AES256"
12617 hapd = hostapd.add_ap(apdev[0], params)
12618 tls = hapd.request("GET tls_library")
12619- if not tls.startswith("OpenSSL"):
12620- raise HwsimSkip("hostapd TLS library is not OpenSSL: " + tls)
12621+ if not tls.startswith("OpenSSL") and not tls.startswith("mbed TLS"):
12622+ raise HwsimSkip("hostapd TLS library is not OpenSSL or mbed TLS: " + tls)
12623 eap_connect(dev[0], hapd, "TTLS", "pap user",
12624 anonymous_identity="ttls", password="password",
12625 ca_cert="auth_serv/ca.pem", phase2="auth=PAP")
12626@@ -6207,14 +6254,26 @@ def test_ap_wpa2_eap_tls_versions(dev, apdev):
12627 check_tls_ver(dev[0], hapd,
12628 "tls_disable_tlsv1_0=1 tls_disable_tlsv1_1=1",
12629 "TLSv1.2")
12630- elif tls.startswith("internal"):
12631+ elif tls.startswith("internal") or tls.startswith("mbed TLS"):
12632 check_tls_ver(dev[0], hapd,
12633 "tls_disable_tlsv1_0=1 tls_disable_tlsv1_1=1", "TLSv1.2")
12634+<<<<<<< HEAD
12635 check_tls_ver(dev[1], hapd,
12636 "tls_disable_tlsv1_0=1 tls_disable_tlsv1_1=0 tls_disable_tlsv1_2=1", "TLSv1.1")
12637 check_tls_ver(dev[2], hapd,
12638 "tls_disable_tlsv1_0=0 tls_disable_tlsv1_1=1 tls_disable_tlsv1_2=1", "TLSv1")
12639 if "run=OpenSSL 1.1.1" in tls or "run=OpenSSL 3." in tls:
12640+=======
12641+ if tls.startswith("mbed TLS"):
12642+ check_tls_ver(dev[2], hapd,
12643+ "tls_disable_tlsv1_0=0 tls_disable_tlsv1_1=1 tls_disable_tlsv1_2=1", "TLSv1.0")
12644+ else:
12645+ check_tls_ver(dev[1], hapd,
12646+ "tls_disable_tlsv1_0=1 tls_disable_tlsv1_1=0 tls_disable_tlsv1_2=1", "TLSv1.1")
12647+ check_tls_ver(dev[2], hapd,
12648+ "tls_disable_tlsv1_0=0 tls_disable_tlsv1_1=1 tls_disable_tlsv1_2=1", "TLSv1")
12649+ if "run=OpenSSL 1.1.1" in tls or "run=OpenSSL 3.0" in tls:
12650+>>>>>>> 585bc9ada (hostapd: sync 2024-01-18 openwrt/trunk patch folder)
12651 check_tls_ver(dev[0], hapd,
12652 "tls_disable_tlsv1_0=1 tls_disable_tlsv1_1=1 tls_disable_tlsv1_2=1 tls_disable_tlsv1_3=0", "TLSv1.3")
12653
12654@@ -6235,6 +6294,11 @@ def test_ap_wpa2_eap_tls_versions_server(dev, apdev):
12655 tests = [("TLSv1", "[ENABLE-TLSv1.0][DISABLE-TLSv1.1][DISABLE-TLSv1.2][DISABLE-TLSv1.3]"),
12656 ("TLSv1.1", "[ENABLE-TLSv1.0][ENABLE-TLSv1.1][DISABLE-TLSv1.2][DISABLE-TLSv1.3]"),
12657 ("TLSv1.2", "[ENABLE-TLSv1.0][ENABLE-TLSv1.1][ENABLE-TLSv1.2][DISABLE-TLSv1.3]")]
12658+ tls = dev[0].request("GET tls_library")
12659+ if tls.startswith("mbed TLS"):
12660+ tests = [#("TLSv1.0", "[ENABLE-TLSv1.0][DISABLE-TLSv1.1][DISABLE-TLSv1.2][DISABLE-TLSv1.3]"),
12661+ #("TLSv1.1", "[ENABLE-TLSv1.0][ENABLE-TLSv1.1][DISABLE-TLSv1.2][DISABLE-TLSv1.3]"),
12662+ ("TLSv1.2", "[ENABLE-TLSv1.0][ENABLE-TLSv1.1][ENABLE-TLSv1.2][DISABLE-TLSv1.3]")]
12663 for exp, flags in tests:
12664 hapd.disable()
12665 hapd.set("tls_flags", flags)
12666@@ -7305,6 +7369,7 @@ def test_ap_wpa2_eap_assoc_rsn(dev, apdev):
12667 def test_eap_tls_ext_cert_check(dev, apdev):
12668 """EAP-TLS and external server certification validation"""
12669 # With internal server certificate chain validation
12670+ check_ext_cert_check_support(dev[0])
12671 id = dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS",
12672 identity="tls user",
12673 ca_cert="auth_serv/ca.pem",
12674@@ -7317,6 +7382,7 @@ def test_eap_tls_ext_cert_check(dev, apdev):
12675 def test_eap_ttls_ext_cert_check(dev, apdev):
12676 """EAP-TTLS and external server certification validation"""
12677 # Without internal server certificate chain validation
12678+ check_ext_cert_check_support(dev[0])
12679 id = dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
12680 identity="pap user", anonymous_identity="ttls",
12681 password="password", phase2="auth=PAP",
12682@@ -7327,6 +7393,7 @@ def test_eap_ttls_ext_cert_check(dev, apdev):
12683 def test_eap_peap_ext_cert_check(dev, apdev):
12684 """EAP-PEAP and external server certification validation"""
12685 # With internal server certificate chain validation
12686+ check_ext_cert_check_support(dev[0])
12687 id = dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="PEAP",
12688 identity="user", anonymous_identity="peap",
12689 ca_cert="auth_serv/ca.pem",
12690@@ -7337,6 +7404,7 @@ def test_eap_peap_ext_cert_check(dev, apdev):
12691
12692 def test_eap_fast_ext_cert_check(dev, apdev):
12693 """EAP-FAST and external server certification validation"""
12694+ check_ext_cert_check_support(dev[0])
12695 check_eap_capa(dev[0], "FAST")
12696 # With internal server certificate chain validation
12697 dev[0].request("SET blob fast_pac_auth_ext ")
12698@@ -7351,10 +7419,6 @@ def test_eap_fast_ext_cert_check(dev, apdev):
12699 run_ext_cert_check(dev, apdev, id)
12700
12701 def run_ext_cert_check(dev, apdev, net_id):
12702- check_ext_cert_check_support(dev[0])
12703- if not openssl_imported:
12704- raise HwsimSkip("OpenSSL python method not available")
12705-
12706 params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
12707 hapd = hostapd.add_ap(apdev[0], params)
12708
12709diff --git a/tests/hwsim/test_ap_ft.py b/tests/hwsim/test_ap_ft.py
12710index 3d07d21f7..a708412de 100644
12711--- a/tests/hwsim/test_ap_ft.py
12712+++ b/tests/hwsim/test_ap_ft.py
12713@@ -2486,11 +2486,11 @@ def test_ap_ft_ap_oom5(dev, apdev):
12714 # This will fail to roam
12715 dev[0].roam(bssid1, check_bssid=False)
12716
12717- with fail_test(hapd1, 1, "sha256_prf_bits;wpa_pmk_r1_to_ptk;wpa_ft_process_auth_req"):
12718+ with fail_test(hapd1, 1, "sha256_prf;wpa_pmk_r1_to_ptk;wpa_ft_process_auth_req"):
12719 # This will fail to roam
12720 dev[0].roam(bssid1, check_bssid=False)
12721
12722- with fail_test(hapd1, 3, "wpa_pmk_r1_to_ptk;wpa_ft_process_auth_req"):
12723+ with fail_test(hapd1, 2, "wpa_pmk_r1_to_ptk;wpa_ft_process_auth_req"):
12724 # This will fail to roam
12725 dev[0].roam(bssid1, check_bssid=False)
12726
12727diff --git a/tests/hwsim/test_authsrv.py b/tests/hwsim/test_authsrv.py
12728index e0665bcb2..02ec301e5 100644
12729--- a/tests/hwsim/test_authsrv.py
12730+++ b/tests/hwsim/test_authsrv.py
12731@@ -156,9 +156,12 @@ def test_authsrv_oom(dev, apdev):
12732 if "FAIL" not in authsrv.request("ENABLE"):
12733 raise Exception("ENABLE succeeded during OOM")
12734
12735- with alloc_fail(authsrv, 1, "tls_init;authsrv_init"):
12736- if "FAIL" not in authsrv.request("ENABLE"):
12737- raise Exception("ENABLE succeeded during OOM")
12738+ # tls_mbedtls.c:tls_init() does not alloc memory (no alloc fail trigger)
12739+ tls = dev[0].request("GET tls_library")
12740+ if not tls.startswith("mbed TLS"):
12741+ with alloc_fail(authsrv, 1, "tls_init;authsrv_init"):
12742+ if "FAIL" not in authsrv.request("ENABLE"):
12743+ raise Exception("ENABLE succeeded during OOM")
12744
12745 for count in range(1, 3):
12746 with alloc_fail(authsrv, count, "eap_sim_db_init;authsrv_init"):
12747diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py
12748index 518983bd0..077de58c9 100644
12749--- a/tests/hwsim/test_dpp.py
12750+++ b/tests/hwsim/test_dpp.py
12751@@ -39,7 +39,8 @@ def check_dpp_capab(dev, brainpool=False, min_ver=1):
12752 raise HwsimSkip("DPP not supported")
12753 if brainpool:
12754 tls = dev.request("GET tls_library")
12755- if (not tls.startswith("OpenSSL") or "run=BoringSSL" in tls) and not tls.startswith("wolfSSL"):
12756+ if (not tls.startswith("OpenSSL") or "run=BoringSSL" in tls) and not tls.startswith("wolfSSL") \
12757+ and not tls.startswith("mbed TLS"):
12758 raise HwsimSkip("Crypto library does not support Brainpool curves: " + tls)
12759 capa = dev.request("GET_CAPABILITY dpp")
12760 ver = 1
12761@@ -3902,6 +3903,9 @@ def test_dpp_proto_auth_req_no_i_proto_key(dev, apdev):
12762
12763 def test_dpp_proto_auth_req_invalid_i_proto_key(dev, apdev):
12764 """DPP protocol testing - invalid I-proto key in Auth Req"""
12765+ tls = dev[0].request("GET tls_library")
12766+ if tls.startswith("mbed TLS"):
12767+ raise HwsimSkip("mbed TLS crypto_ecdh_set_peerkey() properly detects invalid key; no response")
12768 run_dpp_proto_auth_req_missing(dev, 66, "Invalid Initiator Protocol Key")
12769
12770 def test_dpp_proto_auth_req_no_i_nonce(dev, apdev):
12771@@ -3997,7 +4001,12 @@ def test_dpp_proto_auth_resp_no_r_proto_key(dev, apdev):
12772
12773 def test_dpp_proto_auth_resp_invalid_r_proto_key(dev, apdev):
12774 """DPP protocol testing - invalid R-Proto Key in Auth Resp"""
12775- run_dpp_proto_auth_resp_missing(dev, 67, "Invalid Responder Protocol Key")
12776+ tls = dev[0].request("GET tls_library")
12777+ if tls.startswith("mbed TLS"):
12778+ # mbed TLS crypto_ecdh_set_peerkey() properly detects invalid key
12779+ run_dpp_proto_auth_resp_missing(dev, 67, "Failed to derive ECDH shared secret")
12780+ else:
12781+ run_dpp_proto_auth_resp_missing(dev, 67, "Invalid Responder Protocol Key")
12782
12783 def test_dpp_proto_auth_resp_no_r_nonce(dev, apdev):
12784 """DPP protocol testing - no R-nonce in Auth Resp"""
12785@@ -4359,11 +4368,17 @@ def test_dpp_proto_pkex_exchange_resp_invalid_status(dev, apdev):
12786
12787 def test_dpp_proto_pkex_cr_req_invalid_bootstrap_key(dev, apdev):
12788 """DPP protocol testing - invalid Bootstrap Key in PKEX Commit-Reveal Request"""
12789+ tls = dev[0].request("GET tls_library")
12790+ if tls.startswith("mbed TLS"):
12791+ raise HwsimSkip("mbed TLS crypto_ecdh_set_peerkey() properly detects invalid key; no response")
12792 run_dpp_proto_pkex_req_missing(dev, 47,
12793 "Peer bootstrapping key is invalid")
12794
12795 def test_dpp_proto_pkex_cr_resp_invalid_bootstrap_key(dev, apdev):
12796 """DPP protocol testing - invalid Bootstrap Key in PKEX Commit-Reveal Response"""
12797+ tls = dev[0].request("GET tls_library")
12798+ if tls.startswith("mbed TLS"):
12799+ raise HwsimSkip("mbed TLS crypto_ecdh_set_peerkey() properly detects invalid key; no response")
12800 run_dpp_proto_pkex_resp_missing(dev, 48,
12801 "Peer bootstrapping key is invalid")
12802
12803diff --git a/tests/hwsim/test_erp.py b/tests/hwsim/test_erp.py
12804index d083993e8..262e9f095 100644
12805--- a/tests/hwsim/test_erp.py
12806+++ b/tests/hwsim/test_erp.py
12807@@ -12,7 +12,7 @@ import time
12808
12809 import hostapd
12810 from utils import *
12811-from test_ap_eap import int_eap_server_params, check_tls13_support
12812+from test_ap_eap import int_eap_server_params, check_tls13_support, check_eap_capa
12813 from test_ap_psk import find_wpas_process, read_process_memory, verify_not_present, get_key_locations
12814
12815 def test_erp_initiate_reauth_start(dev, apdev):
12816@@ -276,6 +276,7 @@ def test_erp_radius_eap_methods(dev, apdev):
12817 params['erp_domain'] = 'example.com'
12818 params['disable_pmksa_caching'] = '1'
12819 hapd = hostapd.add_ap(apdev[0], params)
12820+ tls = dev[0].request("GET tls_library")
12821
12822 erp_test(dev[0], hapd, eap="AKA", identity="0232010000000000@example.com",
12823 password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123")
12824@@ -289,7 +290,7 @@ def test_erp_radius_eap_methods(dev, apdev):
12825 password="5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123")
12826 erp_test(dev[0], hapd, eap="EKE", identity="erp-eke@example.com",
12827 password="hello")
12828- if "FAST" in eap_methods:
12829+ if "FAST" in eap_methods and check_eap_capa(dev[0], "FAST"):
12830 erp_test(dev[0], hapd, eap="FAST", identity="erp-fast@example.com",
12831 password="password", ca_cert="auth_serv/ca.pem",
12832 phase2="auth=GTC",
12833@@ -301,13 +302,14 @@ def test_erp_radius_eap_methods(dev, apdev):
12834 password="password")
12835 erp_test(dev[0], hapd, eap="PAX", identity="erp-pax@example.com",
12836 password_hex="0123456789abcdef0123456789abcdef")
12837- if "MSCHAPV2" in eap_methods:
12838+ if "MSCHAPV2" in eap_methods and check_eap_capa(dev[0], "MSCHAPV2"):
12839 erp_test(dev[0], hapd, eap="PEAP", identity="erp-peap@example.com",
12840 password="password", ca_cert="auth_serv/ca.pem",
12841 phase2="auth=MSCHAPV2")
12842- erp_test(dev[0], hapd, eap="TEAP", identity="erp-teap@example.com",
12843- password="password", ca_cert="auth_serv/ca.pem",
12844- phase2="auth=MSCHAPV2", pac_file="blob://teap_pac")
12845+ if check_eap_capa(dev[0], "TEAP"):
12846+ erp_test(dev[0], hapd, eap="TEAP", identity="erp-teap@example.com",
12847+ password="password", ca_cert="auth_serv/ca.pem",
12848+ phase2="auth=MSCHAPV2", pac_file="blob://teap_pac")
12849 erp_test(dev[0], hapd, eap="PSK", identity="erp-psk@example.com",
12850 password_hex="0123456789abcdef0123456789abcdef")
12851 if "PWD" in eap_methods:
12852@@ -640,7 +642,7 @@ def test_erp_local_errors(dev, apdev):
12853 dev[0].request("REMOVE_NETWORK all")
12854 dev[0].wait_disconnected()
12855
12856- for count in range(1, 6):
12857+ for count in range(1, 4):
12858 dev[0].request("ERP_FLUSH")
12859 with fail_test(dev[0], count, "hmac_sha256_kdf;eap_peer_erp_init"):
12860 dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
12861diff --git a/tests/hwsim/test_fils.py b/tests/hwsim/test_fils.py
12862index 5cdc28734..17110c5c2 100644
12863--- a/tests/hwsim/test_fils.py
12864+++ b/tests/hwsim/test_fils.py
12865@@ -1484,6 +1484,18 @@ def run_fils_sk_pfs(dev, apdev, group, params):
12866 check_erp_capa(dev[0])
12867 check_ec_group(dev[0], group)
12868
12869+ tls = dev[0].request("GET tls_library")
12870+ if tls.startswith("mbed TLS"):
12871+ if int(group) == 27:
12872+ raise HwsimSkip("Brainpool EC group 27 not supported by mbed TLS")
12873+ elif not tls.startswith("wolfSSL"):
12874+ if int(group) in [25]:
12875+ if not (tls.startswith("OpenSSL") and ("build=OpenSSL 1.0.2" in tls or "build=OpenSSL 1.1" in tls or "build=OpenSSL 3.0" in tls) and ("run=OpenSSL 1.0.2" in tls or "run=OpenSSL 1.1" in tls or "run=OpenSSL 3.0" in tls)):
12876+ raise HwsimSkip("EC group not supported")
12877+ if int(group) in [27, 28, 29, 30]:
12878+ if not (tls.startswith("OpenSSL") and ("build=OpenSSL 1.0.2" in tls or "build=OpenSSL 1.1" in tls or "build=OpenSSL 3.0" in tls) and ("run=OpenSSL 1.0.2" in tls or "run=OpenSSL 1.1" in tls or "run=OpenSSL 3.0" in tls)):
12879+ raise HwsimSkip("Brainpool EC group not supported")
12880+
12881 start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst"))
12882
12883 bssid = apdev[0]['bssid']
12884diff --git a/tests/hwsim/test_pmksa_cache.py b/tests/hwsim/test_pmksa_cache.py
12885index 4a3b444ff..4f7f7f760 100644
12886--- a/tests/hwsim/test_pmksa_cache.py
12887+++ b/tests/hwsim/test_pmksa_cache.py
12888@@ -958,7 +958,7 @@ def test_pmksa_cache_preauth_wpas_oom(dev, apdev):
12889 eap_connect(dev[0], hapd, "PAX", "pax.user@example.com",
12890 password_hex="0123456789abcdef0123456789abcdef",
12891 bssid=apdev[0]['bssid'])
12892- for i in range(1, 11):
12893+ for i in range(1, 10):
12894 with alloc_fail(dev[0], i, "rsn_preauth_init"):
12895 res = dev[0].request("PREAUTH f2:11:22:33:44:55").strip()
12896 logger.info("Iteration %d - PREAUTH command results: %s" % (i, res))
12897@@ -966,7 +966,7 @@ def test_pmksa_cache_preauth_wpas_oom(dev, apdev):
12898 state = dev[0].request('GET_ALLOC_FAIL')
12899 if state.startswith('0:'):
12900 break
12901- time.sleep(0.05)
12902+ time.sleep(0.10)
12903
12904 def test_pmksa_cache_ctrl(dev, apdev):
12905 """PMKSA cache control interface operations"""
12906diff --git a/tests/hwsim/test_sae.py b/tests/hwsim/test_sae.py
12907index aceb92751..6f9ee5669 100644
12908--- a/tests/hwsim/test_sae.py
12909+++ b/tests/hwsim/test_sae.py
12910@@ -178,6 +178,11 @@ def test_sae_groups(dev, apdev):
12911 if tls.startswith("OpenSSL") and "run=OpenSSL 1." in tls:
12912 logger.info("Add Brainpool EC groups since OpenSSL is new enough")
12913 sae_groups += [27, 28, 29, 30]
12914+ if tls.startswith("mbed TLS"):
12915+ # secp224k1 and secp224r1 (26) have prime p = 1 mod 4, and mbedtls
12916+ # does not have code to derive y from compressed format for those curves
12917+ sae_groups = [19, 25, 20, 21, 1, 2, 5, 14, 15, 16, 22, 23, 24]
12918+ sae_groups += [27, 28, 29, 30]
12919 heavy_groups = [14, 15, 16]
12920 suitable_groups = [15, 16, 17, 18, 19, 20, 21]
12921 groups = [str(g) for g in sae_groups]
12922@@ -2194,6 +2199,8 @@ def run_sae_pwe_group(dev, apdev, group):
12923 logger.info("Add Brainpool EC groups since OpenSSL is new enough")
12924 elif tls.startswith("wolfSSL"):
12925 logger.info("Make sure Brainpool EC groups were enabled when compiling wolfSSL")
12926+ elif tls.startswith("mbed TLS"):
12927+ logger.info("Make sure Brainpool EC groups were enabled when compiling mbed TLS")
12928 else:
12929 raise HwsimSkip("Brainpool curve not supported")
12930 start_sae_pwe_ap(apdev[0], group, 2)
12931diff --git a/tests/hwsim/test_suite_b.py b/tests/hwsim/test_suite_b.py
12932index d03a39dee..d703dee95 100644
12933--- a/tests/hwsim/test_suite_b.py
12934+++ b/tests/hwsim/test_suite_b.py
12935@@ -27,6 +27,8 @@ def check_suite_b_tls_lib(dev, dhe=False, level128=False):
12936 return
12937 if tls.startswith("wolfSSL"):
12938 return
12939+ if tls.startswith("mbed TLS"):
12940+ return
12941 if not tls.startswith("OpenSSL"):
12942 raise HwsimSkip("TLS library not supported for Suite B: " + tls)
12943 supported = False
12944@@ -520,6 +522,7 @@ def test_suite_b_192_rsa_insufficient_dh(dev, apdev):
12945
12946 dev[0].connect("test-suite-b", key_mgmt="WPA-EAP-SUITE-B-192",
12947 ieee80211w="2",
12948+ openssl_ciphers="DHE-RSA-AES256-GCM-SHA384",
12949 phase1="tls_suiteb=1",
12950 eap="TLS", identity="tls user",
12951 ca_cert="auth_serv/rsa3072-ca.pem",
12952diff --git a/tests/hwsim/test_wpas_ctrl.py b/tests/hwsim/test_wpas_ctrl.py
12953index 44eb00444..fbe0fb794 100644
12954--- a/tests/hwsim/test_wpas_ctrl.py
12955+++ b/tests/hwsim/test_wpas_ctrl.py
12956@@ -1856,7 +1856,7 @@ def _test_wpas_ctrl_oom(dev):
12957 tls = dev[0].request("GET tls_library")
12958 if not tls.startswith("internal"):
12959 tests.append(('NFC_GET_HANDOVER_SEL NDEF P2P-CR-TAG', 'FAIL',
12960- 4, 'wpas_ctrl_nfc_get_handover_sel_p2p'))
12961+ 3, 'wpas_ctrl_nfc_get_handover_sel_p2p'))
12962 for cmd, exp, count, func in tests:
12963 with alloc_fail(dev[0], count, func):
12964 res = dev[0].request(cmd)
12965diff --git a/tests/hwsim/utils.py b/tests/hwsim/utils.py
12966index 7e3608284..b23c1ee0b 100644
12967--- a/tests/hwsim/utils.py
12968+++ b/tests/hwsim/utils.py
12969@@ -145,7 +145,13 @@ def check_imsi_privacy_support(dev):
12970
12971 def check_tls_tod(dev):
12972 tls = dev.request("GET tls_library")
12973- if not tls.startswith("OpenSSL") and not tls.startswith("internal"):
12974+ if tls.startswith("OpenSSL"):
12975+ return
12976+ elif tls.startswith("internal"):
12977+ return
12978+ elif tls.startswith("mbed TLS"):
12979+ return
12980+ else:
12981 raise HwsimSkip("TLS TOD-TOFU/STRICT not supported with this TLS library: " + tls)
12982
12983 def vht_supported():
12984diff --git a/tests/test-crypto_module.c b/tests/test-crypto_module.c
12985new file mode 100644
12986index 000000000..0f1156142
12987--- /dev/null
12988+++ b/tests/test-crypto_module.c
12989@@ -0,0 +1,16 @@
12990+/*
12991+ * crypto module tests - test program
12992+ * Copyright (c) 2022, Glenn Strauss <gstrauss@gluelogic.com>
12993+ *
12994+ * This software may be distributed under the terms of the BSD license.
12995+ * See README for more details.
12996+ */
12997+
12998+#include "utils/includes.h"
12999+#include "utils/module_tests.h"
13000+#include "crypto/crypto_module_tests.c"
13001+
13002+int main(int argc, char *argv[])
13003+{
13004+ return crypto_module_tests();
13005+}
13006diff --git a/tests/test-https.c b/tests/test-https.c
13007index a72e56f9d..e9df82f1d 100644
13008--- a/tests/test-https.c
13009+++ b/tests/test-https.c
13010@@ -75,7 +75,7 @@ static int https_client(int s, const char *path)
13011 struct tls_connection *conn;
13012 struct wpabuf *in, *out, *appl;
13013 int res = -1;
13014- int need_more_data;
13015+ int need_more_data = 0;
13016
13017 os_memset(&conf, 0, sizeof(conf));
13018 conf.event_cb = https_tls_event_cb;
13019@@ -93,8 +93,12 @@ static int https_client(int s, const char *path)
13020
13021 for (;;) {
13022 appl = NULL;
13023+#ifdef CONFIG_TLS_INTERNAL_SERVER
13024 out = tls_connection_handshake2(tls, conn, in, &appl,
13025 &need_more_data);
13026+#else
13027+ out = tls_connection_handshake(tls, conn, in, &appl);
13028+#endif
13029 wpabuf_free(in);
13030 in = NULL;
13031 if (out == NULL) {
13032@@ -152,11 +156,15 @@ static int https_client(int s, const char *path)
13033
13034 wpa_printf(MSG_INFO, "Reading HTTP response");
13035 for (;;) {
13036- int need_more_data;
13037+ int need_more_data = 0;
13038 in = https_recv(s);
13039 if (in == NULL)
13040 goto done;
13041+#ifdef CONFIG_TLS_INTERNAL_SERVER
13042 out = tls_connection_decrypt2(tls, conn, in, &need_more_data);
13043+#else
13044+ out = tls_connection_decrypt(tls, conn, in);
13045+#endif
13046 if (need_more_data)
13047 wpa_printf(MSG_DEBUG, "HTTP: Need more data");
13048 wpabuf_free(in);
13049diff --git a/tests/test-https_server.c b/tests/test-https_server.c
13050index 33b448682..9dcca5596 100644
13051--- a/tests/test-https_server.c
13052+++ b/tests/test-https_server.c
13053@@ -67,10 +67,12 @@ static struct wpabuf * https_recv(int s, int timeout_ms)
13054 }
13055
13056
13057+#ifdef CONFIG_TLS_INTERNAL_SERVER
13058 static void https_tls_log_cb(void *ctx, const char *msg)
13059 {
13060 wpa_printf(MSG_DEBUG, "TLS: %s", msg);
13061 }
13062+#endif
13063
13064
13065 static int https_server(int s)
13066@@ -79,7 +81,7 @@ static int https_server(int s)
13067 void *tls;
13068 struct tls_connection_params params;
13069 struct tls_connection *conn;
13070- struct wpabuf *in, *out, *appl;
13071+ struct wpabuf *in = NULL, *out = NULL, *appl = NULL;
13072 int res = -1;
13073
13074 os_memset(&conf, 0, sizeof(conf));
13075@@ -106,7 +108,9 @@ static int https_server(int s)
13076 return -1;
13077 }
13078
13079+#ifdef CONFIG_TLS_INTERNAL_SERVER
13080 tls_connection_set_log_cb(conn, https_tls_log_cb, NULL);
13081+#endif
13082
13083 for (;;) {
13084 in = https_recv(s, 5000);
13085@@ -147,12 +151,16 @@ static int https_server(int s)
13086
13087 wpa_printf(MSG_INFO, "Reading HTTP request");
13088 for (;;) {
13089- int need_more_data;
13090+ int need_more_data = 0;
13091
13092 in = https_recv(s, 5000);
13093 if (!in)
13094 goto done;
13095+#ifdef CONFIG_TLS_INTERNAL_SERVER
13096 out = tls_connection_decrypt2(tls, conn, in, &need_more_data);
13097+#else
13098+ out = tls_connection_decrypt(tls, conn, in);
13099+#endif
13100 wpabuf_free(in);
13101 in = NULL;
13102 if (need_more_data) {
13103diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
13104index dd13308f7..c65acab94 100644
13105--- a/wpa_supplicant/Makefile
13106+++ b/wpa_supplicant/Makefile
13107@@ -10,6 +10,7 @@ ALL += dbus/fi.w1.wpa_supplicant1.service
13108 EXTRA_TARGETS=dynamic_eap_methods
13109
13110 CONFIG_FILE=.config
13111+-include $(if $(MULTICALL),../hostapd/.config)
13112 include ../src/build.rules
13113
13114 ifdef CONFIG_BUILD_PASN_SO
13115@@ -188,6 +189,25 @@ ifdef CONFIG_EAPOL_TEST
13116 CFLAGS += -Werror -DEAPOL_TEST
13117 endif
13118
13119+ifdef CONFIG_UBUS
13120+CFLAGS += -DUBUS_SUPPORT
13121+OBJS += ubus.o
13122+LIBS += -lubus
13123+NEED_ULOOP:=y
13124+endif
13125+
13126+ifdef CONFIG_UCODE
13127+CFLAGS += -DUCODE_SUPPORT
13128+OBJS += ../src/utils/ucode.o
13129+OBJS += ucode.o
13130+NEED_ULOOP:=y
13131+endif
13132+
13133+ifdef NEED_ULOOP
13134+OBJS += ../src/utils/uloop.o
13135+LIBS += -lubox
13136+endif
13137+
13138 ifdef CONFIG_CODE_COVERAGE
13139 CFLAGS += -O0 -fprofile-arcs -ftest-coverage -U_FORTIFY_SOURCE
13140 LIBS += -lgcov
13141@@ -334,6 +354,7 @@ endif
13142 ifdef CONFIG_FILS
13143 CFLAGS += -DCONFIG_FILS
13144 NEED_SHA384=y
13145+NEED_HMAC_SHA384_KDF=y
13146 NEED_AES_SIV=y
13147 ifdef CONFIG_FILS_SK_PFS
13148 CFLAGS += -DCONFIG_FILS_SK_PFS
13149@@ -388,7 +409,9 @@ endif
13150 ifdef CONFIG_IBSS_RSN
13151 NEED_RSN_AUTHENTICATOR=y
13152 CFLAGS += -DCONFIG_IBSS_RSN
13153+ifndef MULTICALL
13154 CFLAGS += -DCONFIG_NO_VLAN
13155+endif
13156 OBJS += ibss_rsn.o
13157 endif
13158
13159@@ -980,6 +1003,10 @@ ifdef CONFIG_DYNAMIC_EAP_METHODS
13160 CFLAGS += -DCONFIG_DYNAMIC_EAP_METHODS
13161 LIBS += -ldl -rdynamic
13162 endif
13163+else
13164+ ifdef MULTICALL
13165+ OBJS += ../src/eap_common/eap_common.o
13166+ endif
13167 endif
13168
13169 ifdef CONFIG_AP
13170@@ -987,9 +1014,11 @@ NEED_EAP_COMMON=y
13171 NEED_RSN_AUTHENTICATOR=y
13172 CFLAGS += -DCONFIG_AP
13173 OBJS += ap.o
13174+ifndef MULTICALL
13175 CFLAGS += -DCONFIG_NO_RADIUS
13176 CFLAGS += -DCONFIG_NO_ACCOUNTING
13177 CFLAGS += -DCONFIG_NO_VLAN
13178+endif
13179 OBJS += ../src/ap/hostapd.o
13180 OBJS += ../src/ap/wpa_auth_glue.o
13181 OBJS += ../src/ap/utils.o
13182@@ -1029,7 +1058,16 @@ ifdef CONFIG_FILS
13183 OBJS += ../src/ap/fils_hlp.o
13184 endif
13185 ifdef CONFIG_CTRL_IFACE
13186+ifdef CONFIG_CTRL_IFACE_MIB
13187+CFLAGS += -DCONFIG_CTRL_IFACE_MIB
13188+endif
13189 OBJS += ../src/ap/ctrl_iface_ap.o
13190+ifdef CONFIG_UBUS
13191+OBJS += ../src/ap/ubus.o
13192+endif
13193+ifdef CONFIG_UCODE
13194+OBJS += ../src/ap/ucode.o
13195+endif
13196 endif
13197
13198 CFLAGS += -DEAP_SERVER -DEAP_SERVER_IDENTITY
13199@@ -1080,6 +1118,12 @@ endif
13200 ifdef CONFIG_HS20
13201 OBJS += ../src/ap/hs20.o
13202 endif
13203+else
13204+ ifdef MULTICALL
13205+ OBJS += ../src/eap_server/eap_server.o
13206+ OBJS += ../src/eap_server/eap_server_identity.o
13207+ OBJS += ../src/eap_server/eap_server_methods.o
13208+ endif
13209 endif
13210
13211 ifdef CONFIG_MBO
13212@@ -1089,7 +1133,9 @@ NEED_GAS=y
13213 endif
13214
13215 ifdef NEED_RSN_AUTHENTICATOR
13216+ifndef MULTICALL
13217 CFLAGS += -DCONFIG_NO_RADIUS
13218+endif
13219 NEED_AES_WRAP=y
13220 OBJS += ../src/ap/wpa_auth.o
13221 OBJS += ../src/ap/wpa_auth_ie.o
13222@@ -1188,6 +1234,7 @@ TLS_FUNCS=y
13223 endif
13224
13225 ifeq ($(CONFIG_TLS), wolfssl)
13226+CFLAGS += -DCONFIG_TLS_WOLFSSL
13227 ifdef TLS_FUNCS
13228 CFLAGS += -DWOLFSSL_DER_LOAD
13229 OBJS += ../src/crypto/tls_wolfssl.o
13230@@ -1203,6 +1250,7 @@ LIBS_p += -lwolfssl -lm
13231 endif
13232
13233 ifeq ($(CONFIG_TLS), openssl)
13234+CFLAGS += -DCONFIG_TLS_OPENSSL
13235 CFLAGS += -DCRYPTO_RSA_OAEP_SHA256
13236 ifdef TLS_FUNCS
13237 CFLAGS += -DEAP_TLS_OPENSSL
13238@@ -1229,7 +1277,28 @@ endif
13239 CFLAGS += -DTLS_DEFAULT_CIPHERS=\"$(CONFIG_TLS_DEFAULT_CIPHERS)\"
13240 endif
13241
13242+ifeq ($(CONFIG_TLS), mbedtls)
13243+CFLAGS += -DCONFIG_TLS_MBEDTLS
13244+ifndef CONFIG_CRYPTO
13245+CONFIG_CRYPTO=mbedtls
13246+endif
13247+ifdef TLS_FUNCS
13248+OBJS += ../src/crypto/tls_mbedtls.o
13249+LIBS += -lmbedtls -lmbedx509
13250+endif
13251+OBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o
13252+OBJS_p += ../src/crypto/crypto_$(CONFIG_CRYPTO).o
13253+OBJS_priv += ../src/crypto/crypto_$(CONFIG_CRYPTO).o
13254+ifeq ($(CONFIG_CRYPTO), mbedtls)
13255+LIBS += -lmbedcrypto
13256+LIBS_p += -lmbedcrypto
13257+# XXX: create a config option?
13258+CFLAGS += -DCRYPTO_RSA_OAEP_SHA256
13259+endif
13260+endif
13261+
13262 ifeq ($(CONFIG_TLS), gnutls)
13263+CFLAGS += -DCONFIG_TLS_GNUTLS
13264 ifndef CONFIG_CRYPTO
13265 # default to libgcrypt
13266 CONFIG_CRYPTO=gnutls
13267@@ -1260,6 +1329,7 @@ endif
13268 endif
13269
13270 ifeq ($(CONFIG_TLS), internal)
13271+CFLAGS += -DCONFIG_TLS_INTERNAL
13272 ifndef CONFIG_CRYPTO
13273 CONFIG_CRYPTO=internal
13274 endif
13275@@ -1340,6 +1410,7 @@ endif
13276 endif
13277
13278 ifeq ($(CONFIG_TLS), linux)
13279+CFLAGS += -DCONFIG_TLS_INTERNAL
13280 OBJS += ../src/crypto/crypto_linux.o
13281 OBJS_p += ../src/crypto/crypto_linux.o
13282 ifdef TLS_FUNCS
13283@@ -1421,9 +1492,11 @@ endif
13284
13285 ifneq ($(CONFIG_TLS), openssl)
13286 ifneq ($(CONFIG_TLS), wolfssl)
13287+ifneq ($(CONFIG_TLS), mbedtls)
13288 NEED_INTERNAL_AES_WRAP=y
13289 endif
13290 endif
13291+endif
13292 ifdef CONFIG_OPENSSL_INTERNAL_AES_WRAP
13293 # Seems to be needed at least with BoringSSL
13294 NEED_INTERNAL_AES_WRAP=y
13295@@ -1437,9 +1510,11 @@ endif
13296
13297 ifdef NEED_INTERNAL_AES_WRAP
13298 ifneq ($(CONFIG_TLS), linux)
13299+ifneq ($(CONFIG_TLS), mbedtls)
13300 AESOBJS += ../src/crypto/aes-unwrap.o
13301 endif
13302 endif
13303+endif
13304 ifdef NEED_AES_EAX
13305 AESOBJS += ../src/crypto/aes-eax.o
13306 NEED_AES_CTR=y
13307@@ -1449,35 +1524,45 @@ AESOBJS += ../src/crypto/aes-siv.o
13308 NEED_AES_CTR=y
13309 endif
13310 ifdef NEED_AES_CTR
13311+ifneq ($(CONFIG_TLS), mbedtls)
13312 AESOBJS += ../src/crypto/aes-ctr.o
13313 endif
13314+endif
13315 ifdef NEED_AES_ENCBLOCK
13316+ifneq ($(CONFIG_TLS), mbedtls)
13317 AESOBJS += ../src/crypto/aes-encblock.o
13318 endif
13319+endif
13320 NEED_AES_ENC=y
13321 ifneq ($(CONFIG_TLS), openssl)
13322 ifneq ($(CONFIG_TLS), linux)
13323 ifneq ($(CONFIG_TLS), wolfssl)
13324+ifneq ($(CONFIG_TLS), mbedtls)
13325 AESOBJS += ../src/crypto/aes-omac1.o
13326 endif
13327 endif
13328 endif
13329+endif
13330 ifdef NEED_AES_WRAP
13331 NEED_AES_ENC=y
13332 ifdef NEED_INTERNAL_AES_WRAP
13333+ifneq ($(CONFIG_TLS), mbedtls)
13334 AESOBJS += ../src/crypto/aes-wrap.o
13335 endif
13336 endif
13337+endif
13338 ifdef NEED_AES_CBC
13339 NEED_AES_ENC=y
13340 ifneq ($(CONFIG_TLS), openssl)
13341 ifneq ($(CONFIG_TLS), linux)
13342 ifneq ($(CONFIG_TLS), wolfssl)
13343+ifneq ($(CONFIG_TLS), mbedtls)
13344 AESOBJS += ../src/crypto/aes-cbc.o
13345 endif
13346 endif
13347 endif
13348 endif
13349+endif
13350 ifdef NEED_AES_ENC
13351 ifdef CONFIG_INTERNAL_AES
13352 AESOBJS += ../src/crypto/aes-internal-enc.o
13353@@ -1492,12 +1577,16 @@ ifneq ($(CONFIG_TLS), openssl)
13354 ifneq ($(CONFIG_TLS), linux)
13355 ifneq ($(CONFIG_TLS), gnutls)
13356 ifneq ($(CONFIG_TLS), wolfssl)
13357+ifneq ($(CONFIG_TLS), mbedtls)
13358 SHA1OBJS += ../src/crypto/sha1.o
13359 endif
13360 endif
13361 endif
13362 endif
13363+endif
13364+ifneq ($(CONFIG_TLS), mbedtls)
13365 SHA1OBJS += ../src/crypto/sha1-prf.o
13366+endif
13367 ifdef CONFIG_INTERNAL_SHA1
13368 SHA1OBJS += ../src/crypto/sha1-internal.o
13369 ifdef NEED_FIPS186_2_PRF
13370@@ -1509,29 +1598,37 @@ CFLAGS += -DCONFIG_NO_PBKDF2
13371 else
13372 ifneq ($(CONFIG_TLS), openssl)
13373 ifneq ($(CONFIG_TLS), wolfssl)
13374+ifneq ($(CONFIG_TLS), mbedtls)
13375 SHA1OBJS += ../src/crypto/sha1-pbkdf2.o
13376 endif
13377 endif
13378 endif
13379+endif
13380 ifdef NEED_T_PRF
13381+ifneq ($(CONFIG_TLS), mbedtls)
13382 SHA1OBJS += ../src/crypto/sha1-tprf.o
13383 endif
13384+endif
13385 ifdef NEED_TLS_PRF
13386+ifneq ($(CONFIG_TLS), mbedtls)
13387 SHA1OBJS += ../src/crypto/sha1-tlsprf.o
13388 endif
13389 endif
13390+endif
13391
13392 ifndef CONFIG_FIPS
13393 ifneq ($(CONFIG_TLS), openssl)
13394 ifneq ($(CONFIG_TLS), linux)
13395 ifneq ($(CONFIG_TLS), gnutls)
13396 ifneq ($(CONFIG_TLS), wolfssl)
13397+ifneq ($(CONFIG_TLS), mbedtls)
13398 MD5OBJS += ../src/crypto/md5.o
13399 endif
13400 endif
13401 endif
13402 endif
13403 endif
13404+endif
13405 ifdef NEED_MD5
13406 ifdef CONFIG_INTERNAL_MD5
13407 MD5OBJS += ../src/crypto/md5-internal.o
13408@@ -1586,12 +1683,17 @@ ifneq ($(CONFIG_TLS), openssl)
13409 ifneq ($(CONFIG_TLS), linux)
13410 ifneq ($(CONFIG_TLS), gnutls)
13411 ifneq ($(CONFIG_TLS), wolfssl)
13412+ifneq ($(CONFIG_TLS), mbedtls)
13413 SHA256OBJS += ../src/crypto/sha256.o
13414 endif
13415 endif
13416 endif
13417 endif
13418+endif
13419+
13420+ifneq ($(CONFIG_TLS), mbedtls)
13421 SHA256OBJS += ../src/crypto/sha256-prf.o
13422+endif
13423 ifdef CONFIG_INTERNAL_SHA256
13424 SHA256OBJS += ../src/crypto/sha256-internal.o
13425 endif
13426@@ -1604,50 +1706,68 @@ CFLAGS += -DCONFIG_INTERNAL_SHA512
13427 SHA256OBJS += ../src/crypto/sha512-internal.o
13428 endif
13429 ifdef NEED_TLS_PRF_SHA256
13430+ifneq ($(CONFIG_TLS), mbedtls)
13431 SHA256OBJS += ../src/crypto/sha256-tlsprf.o
13432 endif
13433+endif
13434 ifdef NEED_TLS_PRF_SHA384
13435+ifneq ($(CONFIG_TLS), mbedtls)
13436 SHA256OBJS += ../src/crypto/sha384-tlsprf.o
13437 endif
13438+endif
13439 ifdef NEED_HMAC_SHA256_KDF
13440 CFLAGS += -DCONFIG_HMAC_SHA256_KDF
13441+ifneq ($(CONFIG_TLS), mbedtls)
13442 OBJS += ../src/crypto/sha256-kdf.o
13443 endif
13444+endif
13445 ifdef NEED_HMAC_SHA384_KDF
13446 CFLAGS += -DCONFIG_HMAC_SHA384_KDF
13447+ifneq ($(CONFIG_TLS), mbedtls)
13448 OBJS += ../src/crypto/sha384-kdf.o
13449 endif
13450+endif
13451 ifdef NEED_HMAC_SHA512_KDF
13452 CFLAGS += -DCONFIG_HMAC_SHA512_KDF
13453+ifneq ($(CONFIG_TLS), mbedtls)
13454 OBJS += ../src/crypto/sha512-kdf.o
13455 endif
13456+endif
13457 OBJS += $(SHA256OBJS)
13458 ifdef NEED_SHA384
13459 ifneq ($(CONFIG_TLS), openssl)
13460 ifneq ($(CONFIG_TLS), linux)
13461 ifneq ($(CONFIG_TLS), gnutls)
13462 ifneq ($(CONFIG_TLS), wolfssl)
13463+ifneq ($(CONFIG_TLS), mbedtls)
13464 OBJS += ../src/crypto/sha384.o
13465 endif
13466 endif
13467 endif
13468 endif
13469+endif
13470 CFLAGS += -DCONFIG_SHA384
13471+ifneq ($(CONFIG_TLS), mbedtls)
13472 OBJS += ../src/crypto/sha384-prf.o
13473 endif
13474+endif
13475 ifdef NEED_SHA512
13476 ifneq ($(CONFIG_TLS), openssl)
13477 ifneq ($(CONFIG_TLS), linux)
13478 ifneq ($(CONFIG_TLS), gnutls)
13479 ifneq ($(CONFIG_TLS), wolfssl)
13480+ifneq ($(CONFIG_TLS), mbedtls)
13481 OBJS += ../src/crypto/sha512.o
13482 endif
13483 endif
13484 endif
13485 endif
13486+endif
13487 CFLAGS += -DCONFIG_SHA512
13488+ifneq ($(CONFIG_TLS), mbedtls)
13489 OBJS += ../src/crypto/sha512-prf.o
13490 endif
13491+endif
13492
13493 ifdef NEED_ASN1
13494 OBJS += ../src/tls/asn1.o
13495@@ -1822,10 +1942,12 @@ ifdef CONFIG_FIPS
13496 CFLAGS += -DCONFIG_FIPS
13497 ifneq ($(CONFIG_TLS), openssl)
13498 ifneq ($(CONFIG_TLS), wolfssl)
13499+ifneq ($(CONFIG_TLS), mbedtls)
13500 $(error CONFIG_FIPS=y requires CONFIG_TLS=openssl)
13501 endif
13502 endif
13503 endif
13504+endif
13505
13506 OBJS += $(SHA1OBJS) $(DESOBJS)
13507
13508@@ -2003,32 +2125,38 @@ wpa_priv: $(BCHECK) $(OBJS_priv)
13509
13510 _OBJS_VAR := OBJS
13511 include ../src/objs.mk
13512+wpa_supplicant_multi.a: .config $(BCHECK) $(OBJS) $(EXTRA_progs)
13513+ $(Q)$(CC) -c -o wpa_supplicant_multi.o -Dmain=wpa_supplicant_main $(CFLAGS) main.c
13514+ @$(E) " CC " $<
13515+ @rm -f $@
13516+ @$(AR) cr $@ wpa_supplicant_multi.o $(OBJS)
13517+
13518 wpa_supplicant: $(BCHECK) $(OBJS) $(EXTRA_progs)
13519- $(Q)$(LDO) $(LDFLAGS) -o wpa_supplicant $(OBJS) $(LIBS) $(EXTRALIBS)
13520+ +$(Q)$(LDO) $(LDFLAGS) -o wpa_supplicant $(OBJS) $(LIBS) $(EXTRALIBS)
13521 @$(E) " LD " $@
13522
13523 _OBJS_VAR := OBJS_t
13524 include ../src/objs.mk
13525 eapol_test: $(OBJS_t)
13526- $(Q)$(LDO) $(LDFLAGS) -o eapol_test $(OBJS_t) $(LIBS)
13527+ +$(Q)$(LDO) $(LDFLAGS) -o eapol_test $(OBJS_t) $(LIBS)
13528 @$(E) " LD " $@
13529
13530 _OBJS_VAR := OBJS_t2
13531 include ../src/objs.mk
13532 preauth_test: $(OBJS_t2)
13533- $(Q)$(LDO) $(LDFLAGS) -o preauth_test $(OBJS_t2) $(LIBS)
13534+ +$(Q)$(LDO) $(LDFLAGS) -o preauth_test $(OBJS_t2) $(LIBS)
13535 @$(E) " LD " $@
13536
13537 _OBJS_VAR := OBJS_p
13538 include ../src/objs.mk
13539 wpa_passphrase: $(OBJS_p)
13540- $(Q)$(LDO) $(LDFLAGS) -o wpa_passphrase $(OBJS_p) $(LIBS_p) $(LIBS)
13541+ +$(Q)$(LDO) $(LDFLAGS) -o wpa_passphrase $(OBJS_p) $(LIBS_p) $(LIBS)
13542 @$(E) " LD " $@
13543
13544 _OBJS_VAR := OBJS_c
13545 include ../src/objs.mk
13546 wpa_cli: $(OBJS_c)
13547- $(Q)$(LDO) $(LDFLAGS) -o wpa_cli $(OBJS_c) $(LIBS_c)
13548+ +$(Q)$(LDO) $(LDFLAGS) -o wpa_cli $(OBJS_c) $(LIBS_c)
13549 @$(E) " LD " $@
13550
13551 LIBCTRL += ../src/common/wpa_ctrl.o
13552@@ -2135,6 +2263,12 @@ eap_gpsk.so: $(SRC_EAP_GPSK)
13553 $(Q)sed -e 's|\@BINDIR\@|$(BINDIR)|g' $< >$@
13554 @$(E) " sed" $<
13555
13556+dump_cflags:
13557+ @printf "%s " "$(CFLAGS)"
13558+
13559+dump_ldflags:
13560+ @printf "%s " "$(LDFLAGS) $(LIBS) $(EXTRALIBS)"
13561+
13562 wpa_supplicant.exe: wpa_supplicant
13563 mv -f $< $@
13564 wpa_cli.exe: wpa_cli
13565diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
13566index 69a0e5ee1..43c39d7ce 100644
13567--- a/wpa_supplicant/ap.c
13568+++ b/wpa_supplicant/ap.c
13569@@ -1520,7 +1520,7 @@ int wpas_ap_wps_nfc_report_handover(struct wpa_supplicant *wpa_s,
13570 #endif /* CONFIG_WPS */
13571
13572
13573-#ifdef CONFIG_CTRL_IFACE
13574+#if defined(CONFIG_CTRL_IFACE) && defined(CONFIG_CTRL_IFACE_MIB)
13575
13576 int ap_ctrl_iface_sta_first(struct wpa_supplicant *wpa_s,
13577 char *buf, size_t buflen)
13578@@ -1846,11 +1846,31 @@ int ap_switch_channel(struct wpa_supplicant *wpa_s,
13579
13580
13581 #ifdef CONFIG_CTRL_IFACE
13582+
13583+static int __ap_ctrl_iface_chanswitch(struct hostapd_iface *iface,
13584+ struct csa_settings *settings)
13585+{
13586+#ifdef NEED_AP_MLME
13587+ if (!iface || !iface->bss[0])
13588+ return 0;
13589+
13590+ return hostapd_switch_channel(iface->bss[0], settings);
13591+#else
13592+ return -1;
13593+#endif
13594+}
13595+
13596+
13597 int ap_ctrl_iface_chanswitch(struct wpa_supplicant *wpa_s, const char *pos)
13598 {
13599 struct csa_settings settings;
13600 int ret = hostapd_parse_csa_settings(pos, &settings);
13601
13602+ if (!(wpa_s->ap_iface && wpa_s->ap_iface->bss[0]) &&
13603+ !(wpa_s->ifmsh && wpa_s->ifmsh->bss[0]))
13604+ return -1;
13605+
13606+ ret = __ap_ctrl_iface_chanswitch(wpa_s->ap_iface, &settings);
13607 if (ret)
13608 return ret;
13609
13610diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
13611index 2c756136c..c3943355d 100644
13612--- a/wpa_supplicant/config.c
13613+++ b/wpa_supplicant/config.c
13614@@ -18,6 +18,7 @@
13615 #include "eap_peer/eap.h"
13616 #include "p2p/p2p.h"
13617 #include "fst/fst.h"
13618+#include "ap/sta_info.h"
13619 #include "config.h"
13620
13621
13622@@ -2421,6 +2422,97 @@ static char * wpa_config_write_mac_value(const struct parse_data *data,
13623 #endif /* NO_CONFIG_WRITE */
13624
13625
13626+static int wpa_config_parse_mcast_rate(const struct parse_data *data,
13627+ struct wpa_ssid *ssid, int line,
13628+ const char *value)
13629+{
13630+ ssid->mcast_rate = (int)(strtod(value, NULL) * 10);
13631+
13632+ return 0;
13633+}
13634+
13635+#ifndef NO_CONFIG_WRITE
13636+static char * wpa_config_write_mcast_rate(const struct parse_data *data,
13637+ struct wpa_ssid *ssid)
13638+{
13639+ char *value;
13640+ int res;
13641+
13642+ if (!ssid->mcast_rate == 0)
13643+ return NULL;
13644+
13645+ value = os_malloc(6); /* longest: 300.0 */
13646+ if (value == NULL)
13647+ return NULL;
13648+ res = os_snprintf(value, 5, "%.1f", (double)ssid->mcast_rate / 10);
13649+ if (res < 0) {
13650+ os_free(value);
13651+ return NULL;
13652+ }
13653+ return value;
13654+}
13655+#endif /* NO_CONFIG_WRITE */
13656+
13657+static int wpa_config_parse_rates(const struct parse_data *data,
13658+ struct wpa_ssid *ssid, int line,
13659+ const char *value)
13660+{
13661+ int i;
13662+ char *pos, *r, *sptr, *end;
13663+ double rate;
13664+
13665+ pos = (char *)value;
13666+ r = strtok_r(pos, ",", &sptr);
13667+ i = 0;
13668+ while (pos && i < WLAN_SUPP_RATES_MAX) {
13669+ rate = 0.0;
13670+ if (r)
13671+ rate = strtod(r, &end);
13672+ ssid->rates[i] = rate * 2;
13673+ if (*end != '\0' || rate * 2 != ssid->rates[i])
13674+ return 1;
13675+
13676+ i++;
13677+ r = strtok_r(NULL, ",", &sptr);
13678+ }
13679+
13680+ return 0;
13681+}
13682+
13683+#ifndef NO_CONFIG_WRITE
13684+static char * wpa_config_write_rates(const struct parse_data *data,
13685+ struct wpa_ssid *ssid)
13686+{
13687+ char *value, *pos;
13688+ int res, i;
13689+
13690+ if (ssid->rates[0] <= 0)
13691+ return NULL;
13692+
13693+ value = os_malloc(6 * WLAN_SUPP_RATES_MAX + 1);
13694+ if (value == NULL)
13695+ return NULL;
13696+ pos = value;
13697+ for (i = 0; i < WLAN_SUPP_RATES_MAX - 1; i++) {
13698+ res = os_snprintf(pos, 6, "%.1f,", (double)ssid->rates[i] / 2);
13699+ if (res < 0) {
13700+ os_free(value);
13701+ return NULL;
13702+ }
13703+ pos += res;
13704+ }
13705+ res = os_snprintf(pos, 6, "%.1f",
13706+ (double)ssid->rates[WLAN_SUPP_RATES_MAX - 1] / 2);
13707+ if (res < 0) {
13708+ os_free(value);
13709+ return NULL;
13710+ }
13711+
13712+ value[6 * WLAN_SUPP_RATES_MAX] = '\0';
13713+ return value;
13714+}
13715+#endif /* NO_CONFIG_WRITE */
13716+
13717 /* Helper macros for network block parser */
13718
13719 #ifdef OFFSET
13720@@ -2639,6 +2731,7 @@ static const struct parse_data ssid_fields[] = {
13721 #else /* CONFIG_MESH */
13722 { INT_RANGE(mode, 0, 4) },
13723 #endif /* CONFIG_MESH */
13724+ { INT_RANGE(noscan, 0, 1) },
13725 { INT_RANGE(proactive_key_caching, 0, 1) },
13726 { INT_RANGE(disabled, 0, 2) },
13727 { STR(id_str) },
13728@@ -2712,6 +2805,8 @@ static const struct parse_data ssid_fields[] = {
13729 { INT(ap_max_inactivity) },
13730 { INT(dtim_period) },
13731 { INT(beacon_int) },
13732+ { FUNC(rates) },
13733+ { FUNC(mcast_rate) },
13734 #ifdef CONFIG_MACSEC
13735 { INT_RANGE(macsec_policy, 0, 1) },
13736 { INT_RANGE(macsec_integ_only, 0, 1) },
13737diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
13738index 1a2c0c9be..7a3ed6373 100644
13739--- a/wpa_supplicant/config_file.c
13740+++ b/wpa_supplicant/config_file.c
13741@@ -326,8 +326,13 @@ struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp,
13742 while (cred_tail && cred_tail->next)
13743 cred_tail = cred_tail->next;
13744
13745+ if (!strncmp(name, "data:", 5)) {
13746+ f = fmemopen((void *)(name + 5), strlen(name + 5), "r");
13747+ name = "<inline>";
13748+ } else {
13749+ f = fopen(name, "r");
13750+ }
13751 wpa_printf(MSG_DEBUG, "Reading configuration file '%s'", name);
13752- f = fopen(name, "r");
13753 if (f == NULL) {
13754 wpa_printf(MSG_ERROR, "Failed to open config file '%s', "
13755 "error: %s", name, strerror(errno));
13756@@ -775,6 +780,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
13757 #endif /* IEEE8021X_EAPOL */
13758 INT(mode);
13759 INT(no_auto_peer);
13760+ INT(noscan);
13761 INT(mesh_fwding);
13762 INT(frequency);
13763 INT(enable_edmg);
13764diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
13765index e40650c27..de79972b6 100644
13766--- a/wpa_supplicant/config_ssid.h
13767+++ b/wpa_supplicant/config_ssid.h
13768@@ -10,8 +10,10 @@
13769 #define CONFIG_SSID_H
13770
13771 #include "common/defs.h"
13772+#include "ap/sta_info.h"
13773 #include "utils/list.h"
13774 #include "eap_peer/eap_config.h"
13775+#include "drivers/nl80211_copy.h"
13776
13777
13778 #define DEFAULT_EAP_WORKAROUND ((unsigned int) -1)
13779@@ -879,6 +881,9 @@ struct wpa_ssid {
13780 */
13781 void *parent_cred;
13782
13783+ unsigned char rates[WLAN_SUPP_RATES_MAX];
13784+ double mcast_rate;
13785+
13786 #ifdef CONFIG_MACSEC
13787 /**
13788 * macsec_policy - Determines the policy for MACsec secure session
13789@@ -1035,6 +1040,8 @@ struct wpa_ssid {
13790 */
13791 int no_auto_peer;
13792
13793+ int noscan;
13794+
13795 /**
13796 * mesh_rssi_threshold - Set mesh parameter mesh_rssi_threshold (dBm)
13797 *
13798diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
13799index d0fda4cd9..ec45f29bb 100644
13800--- a/wpa_supplicant/ctrl_iface.c
13801+++ b/wpa_supplicant/ctrl_iface.c
13802@@ -2355,7 +2355,7 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
13803 pos += ret;
13804 }
13805
13806-#ifdef CONFIG_AP
13807+#if defined(CONFIG_AP) && defined(CONFIG_CTRL_IFACE_MIB)
13808 if (wpa_s->ap_iface) {
13809 pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
13810 end - pos,
13811@@ -12542,6 +12542,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
13812 reply_len = -1;
13813 } else if (os_strncmp(buf, "NOTE ", 5) == 0) {
13814 wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
13815+#ifdef CONFIG_CTRL_IFACE_MIB
13816 } else if (os_strcmp(buf, "MIB") == 0) {
13817 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
13818 if (reply_len >= 0) {
13819@@ -12554,6 +12555,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
13820 reply_size - reply_len);
13821 #endif /* CONFIG_MACSEC */
13822 }
13823+#endif
13824 } else if (os_strncmp(buf, "STATUS", 6) == 0) {
13825 reply_len = wpa_supplicant_ctrl_iface_status(
13826 wpa_s, buf + 6, reply, reply_size);
13827@@ -13042,6 +13044,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
13828 reply_len = wpa_supplicant_ctrl_iface_bss(
13829 wpa_s, buf + 4, reply, reply_size);
13830 #ifdef CONFIG_AP
13831+#ifdef CONFIG_CTRL_IFACE_MIB
13832 } else if (os_strcmp(buf, "STA-FIRST") == 0) {
13833 reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
13834 } else if (os_strncmp(buf, "STA ", 4) == 0) {
13835@@ -13050,12 +13053,15 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
13836 } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
13837 reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
13838 reply_size);
13839+#endif
13840+#ifdef CONFIG_CTRL_IFACE_MIB
13841 } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
13842 if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15))
13843 reply_len = -1;
13844 } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
13845 if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13))
13846 reply_len = -1;
13847+#endif
13848 } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
13849 if (ap_ctrl_iface_chanswitch(wpa_s, buf + 12))
13850 reply_len = -1;
13851@@ -13214,7 +13220,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
13852 if (wpas_ctrl_iface_coloc_intf_report(wpa_s, buf + 18))
13853 reply_len = -1;
13854 #endif /* CONFIG_WNM */
13855-#ifdef CONFIG_WNM_AP
13856+#if defined(CONFIG_AP) && defined(CONFIG_WNM_AP)
13857 } else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
13858 if (ap_ctrl_iface_disassoc_imminent(wpa_s, buf + 18))
13859 reply_len = -1;
13860@@ -13224,7 +13230,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
13861 } else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) {
13862 if (ap_ctrl_iface_bss_tm_req(wpa_s, buf + 11))
13863 reply_len = -1;
13864-#endif /* CONFIG_WNM_AP */
13865+#endif /* CONFIG_AP && CONFIG_WNM_AP */
13866 } else if (os_strcmp(buf, "FLUSH") == 0) {
13867 wpa_supplicant_ctrl_iface_flush(wpa_s);
13868 } else if (os_strncmp(buf, "RADIO_WORK ", 11) == 0) {
13869diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig
13870index 52befd8f1..ace6c5530 100644
13871--- a/wpa_supplicant/defconfig
13872+++ b/wpa_supplicant/defconfig
13873@@ -10,8 +10,8 @@
13874 # to override previous values of the variables.
13875
13876
13877-# Uncomment following two lines and fix the paths if you have installed OpenSSL
13878-# or GnuTLS in non-default location
13879+# Uncomment following two lines and fix the paths if you have installed TLS
13880+# libraries in a non-default location
13881 #CFLAGS += -I/usr/local/openssl/include
13882 #LIBS += -L/usr/local/openssl/lib
13883
13884@@ -20,6 +20,7 @@
13885 # used to fix build issues on such systems (krb5.h not found).
13886 #CFLAGS += -I/usr/include/kerberos
13887
13888+
13889 # Driver interface for generic Linux wireless extensions
13890 # Note: WEXT is deprecated in the current Linux kernel version and no new
13891 # functionality is added to it. nl80211-based interface is the new
13892@@ -329,6 +330,7 @@ CONFIG_BACKEND=file
13893 # openssl = OpenSSL (default)
13894 # gnutls = GnuTLS
13895 # internal = Internal TLSv1 implementation (experimental)
13896+# mbedtls = mbed TLS
13897 # linux = Linux kernel AF_ALG and internal TLSv1 implementation (experimental)
13898 # none = Empty template
13899 #CONFIG_TLS=openssl
13900diff --git a/wpa_supplicant/eapol_test.c b/wpa_supplicant/eapol_test.c
13901index 95953de92..673c3cc11 100644
13902--- a/wpa_supplicant/eapol_test.c
13903+++ b/wpa_supplicant/eapol_test.c
13904@@ -31,7 +31,12 @@
13905 #include "ctrl_iface.h"
13906 #include "pcsc_funcs.h"
13907 #include "wpas_glue.h"
13908+#include "drivers/driver.h"
13909
13910+void (*wpa_supplicant_event)(void *ctx, enum wpa_event_type event,
13911+ union wpa_event_data *data);
13912+void (*wpa_supplicant_event_global)(void *ctx, enum wpa_event_type event,
13913+ union wpa_event_data *data);
13914
13915 const struct wpa_driver_ops *const wpa_drivers[] = { NULL };
13916
13917@@ -1325,6 +1330,10 @@ static void usage(void)
13918 "option several times.\n");
13919 }
13920
13921+extern void supplicant_event(void *ctx, enum wpa_event_type event,
13922+ union wpa_event_data *data);
13923+extern void supplicant_event_global(void *ctx, enum wpa_event_type event,
13924+ union wpa_event_data *data);
13925
13926 int main(int argc, char *argv[])
13927 {
13928@@ -1348,6 +1357,8 @@ int main(int argc, char *argv[])
13929 if (os_program_init())
13930 return -1;
13931
13932+ wpa_supplicant_event = supplicant_event;
13933+ wpa_supplicant_event_global = supplicant_event_global;
13934 hostapd_logger_register_cb(hostapd_logger_cb);
13935
13936 os_memset(&eapol_test, 0, sizeof(eapol_test));
13937diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
13938index ca2794638..2a9342318 100644
13939--- a/wpa_supplicant/events.c
13940+++ b/wpa_supplicant/events.c
13941@@ -2935,8 +2935,6 @@ void wnm_bss_keep_alive_deinit(struct wpa_supplicant *wpa_s)
13942 }
13943
13944
13945-#ifdef CONFIG_INTERWORKING
13946-
13947 static int wpas_qos_map_set(struct wpa_supplicant *wpa_s, const u8 *qos_map,
13948 size_t len)
13949 {
13950@@ -2969,8 +2967,6 @@ static void interworking_process_assoc_resp(struct wpa_supplicant *wpa_s,
13951 }
13952 }
13953
13954-#endif /* CONFIG_INTERWORKING */
13955-
13956
13957 static void wpa_supplicant_set_4addr_mode(struct wpa_supplicant *wpa_s)
13958 {
13959@@ -3349,10 +3345,8 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
13960 wnm_process_assoc_resp(wpa_s, data->assoc_info.resp_ies,
13961 data->assoc_info.resp_ies_len);
13962 #endif /* CONFIG_WNM */
13963-#ifdef CONFIG_INTERWORKING
13964 interworking_process_assoc_resp(wpa_s, data->assoc_info.resp_ies,
13965 data->assoc_info.resp_ies_len);
13966-#endif /* CONFIG_INTERWORKING */
13967 if (wpa_s->hw_capab == CAPAB_VHT &&
13968 get_ie(data->assoc_info.resp_ies,
13969 data->assoc_info.resp_ies_len, WLAN_EID_VHT_CAP))
13970@@ -5928,8 +5922,8 @@ static void wpas_link_reconfig(struct wpa_supplicant *wpa_s)
13971 }
13972
13973
13974-void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
13975- union wpa_event_data *data)
13976+void supplicant_event(void *ctx, enum wpa_event_type event,
13977+ union wpa_event_data *data)
13978 {
13979 struct wpa_supplicant *wpa_s = ctx;
13980 int resched;
13981@@ -5964,6 +5958,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
13982 event_to_string(event), event);
13983 #endif /* CONFIG_NO_STDOUT_DEBUG */
13984
13985+ wpas_ucode_event(wpa_s, event, data);
13986 switch (event) {
13987 case EVENT_AUTH:
13988 #ifdef CONFIG_FST
13989@@ -6881,7 +6876,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
13990 }
13991
13992
13993-void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
13994+void supplicant_event_global(void *ctx, enum wpa_event_type event,
13995 union wpa_event_data *data)
13996 {
13997 struct wpa_supplicant *wpa_s;
13998diff --git a/wpa_supplicant/main.c b/wpa_supplicant/main.c
13999index 9229eb51f..ee152c5b9 100644
14000--- a/wpa_supplicant/main.c
14001+++ b/wpa_supplicant/main.c
14002@@ -12,6 +12,7 @@
14003 #endif /* __linux__ */
14004
14005 #include "common.h"
14006+#include "build_features.h"
14007 #include "crypto/crypto.h"
14008 #include "fst/fst.h"
14009 #include "wpa_supplicant_i.h"
14010@@ -202,7 +203,7 @@ int main(int argc, char *argv[])
14011
14012 for (;;) {
14013 c = getopt(argc, argv,
14014- "b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuvW");
14015+ "b:Bc:C:D:de:f:g:G:hi:I:KLMm:nNo:O:p:P:qsTtuv::W");
14016 if (c < 0)
14017 break;
14018 switch (c) {
14019@@ -267,6 +268,9 @@ int main(int argc, char *argv[])
14020 params.conf_p2p_dev = optarg;
14021 break;
14022 #endif /* CONFIG_P2P */
14023+ case 'n':
14024+ iface_count = 0;
14025+ break;
14026 case 'o':
14027 params.override_driver = optarg;
14028 break;
14029@@ -302,8 +306,12 @@ int main(int argc, char *argv[])
14030 break;
14031 #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
14032 case 'v':
14033- printf("%s\n", wpa_supplicant_version);
14034- exitcode = 0;
14035+ if (optarg) {
14036+ exitcode = !has_feature(optarg);
14037+ } else {
14038+ printf("%s\n", wpa_supplicant_version);
14039+ exitcode = 0;
14040+ }
14041 goto out;
14042 case 'W':
14043 params.wait_for_monitor++;
14044diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c
14045index 85c1ea8ba..dabbb0334 100644
14046--- a/wpa_supplicant/mesh.c
14047+++ b/wpa_supplicant/mesh.c
14048@@ -506,6 +506,8 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
14049 frequency);
14050 goto out_free;
14051 }
14052+ if (conf->noscan)
14053+ ssid->noscan = 1;
14054
14055 if (ssid->mesh_basic_rates == NULL) {
14056 /*
14057@@ -630,6 +632,7 @@ int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s,
14058
14059 params->meshid = ssid->ssid;
14060 params->meshid_len = ssid->ssid_len;
14061+ params->mcast_rate = ssid->mcast_rate;
14062 ibss_mesh_setup_freq(wpa_s, ssid, &params->freq);
14063 wpa_s->mesh_ht_enabled = !!params->freq.ht_enabled;
14064 wpa_s->mesh_vht_enabled = !!params->freq.vht_enabled;
14065diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
14066index 60f85624f..67352a121 100644
14067--- a/wpa_supplicant/wpa_cli.c
14068+++ b/wpa_supplicant/wpa_cli.c
14069@@ -26,6 +26,15 @@
14070 #include <cutils/properties.h>
14071 #endif /* ANDROID */
14072
14073+#ifndef CONFIG_P2P
14074+#define CONFIG_P2P
14075+#endif
14076+#ifndef CONFIG_AP
14077+#define CONFIG_AP
14078+#endif
14079+#ifndef CONFIG_MESH
14080+#define CONFIG_MESH
14081+#endif
14082
14083 static const char *const wpa_cli_version =
14084 "wpa_cli v" VERSION_STR "\n"
14085diff --git a/wpa_supplicant/wpa_priv.c b/wpa_supplicant/wpa_priv.c
14086index 88f3f2a52..92efe5629 100644
14087--- a/wpa_supplicant/wpa_priv.c
14088+++ b/wpa_supplicant/wpa_priv.c
14089@@ -1042,8 +1042,8 @@ static void wpa_priv_send_ft_response(struct wpa_priv_interface *iface,
14090 }
14091
14092
14093-void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
14094- union wpa_event_data *data)
14095+static void supplicant_event(void *ctx, enum wpa_event_type event,
14096+ union wpa_event_data *data)
14097 {
14098 struct wpa_priv_interface *iface = ctx;
14099
14100@@ -1106,7 +1106,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
14101 }
14102
14103
14104-void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
14105+void supplicant_event_global(void *ctx, enum wpa_event_type event,
14106 union wpa_event_data *data)
14107 {
14108 struct wpa_priv_global *global = ctx;
14109@@ -1220,6 +1220,8 @@ int main(int argc, char *argv[])
14110 if (os_program_init())
14111 return -1;
14112
14113+ wpa_supplicant_event = supplicant_event;
14114+ wpa_supplicant_event_global = supplicant_event_global;
14115 wpa_priv_fd_workaround();
14116
14117 os_memset(&global, 0, sizeof(global));
14118diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
14119index ab71e2f27..fea84fe49 100644
14120--- a/wpa_supplicant/wpa_supplicant.c
14121+++ b/wpa_supplicant/wpa_supplicant.c
14122@@ -1060,6 +1060,7 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
14123 sme_sched_obss_scan(wpa_s, 0);
14124 }
14125 wpa_s->wpa_state = state;
14126+ wpas_ucode_update_state(wpa_s);
14127
14128 #ifdef CONFIG_BGSCAN
14129 if (state == WPA_COMPLETED && wpa_s->current_ssid != wpa_s->bgscan_ssid)
14130@@ -2698,7 +2699,7 @@ static int drv_supports_vht(struct wpa_supplicant *wpa_s,
14131 }
14132
14133
14134-static bool ibss_mesh_is_80mhz_avail(int channel, struct hostapd_hw_modes *mode)
14135+static bool ibss_mesh_is_80mhz_avail(int channel, struct hostapd_hw_modes *mode, bool dfs_enabled)
14136 {
14137 int i;
14138
14139@@ -2707,7 +2708,10 @@ static bool ibss_mesh_is_80mhz_avail(int channel, struct hostapd_hw_modes *mode)
14140
14141 chan = hw_get_channel_chan(mode, i, NULL);
14142 if (!chan ||
14143- chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
14144+ chan->flag & HOSTAPD_CHAN_DISABLED)
14145+ return false;
14146+
14147+ if (!dfs_enabled && chan->flag & (HOSTAPD_CHAN_RADAR | HOSTAPD_CHAN_NO_IR))
14148 return false;
14149 }
14150
14151@@ -2767,7 +2771,7 @@ static bool ibss_mesh_can_use_vht(struct wpa_supplicant *wpa_s,
14152 const struct wpa_ssid *ssid,
14153 struct hostapd_hw_modes *mode)
14154 {
14155- if (mode->mode != HOSTAPD_MODE_IEEE80211A)
14156+ if (mode->mode != HOSTAPD_MODE_IEEE80211A && !(ssid->noscan))
14157 return false;
14158
14159 if (!drv_supports_vht(wpa_s, ssid))
14160@@ -2834,12 +2838,13 @@ static void ibss_mesh_select_40mhz(struct wpa_supplicant *wpa_s,
14161 const struct wpa_ssid *ssid,
14162 struct hostapd_hw_modes *mode,
14163 struct hostapd_freq_params *freq,
14164- int obss_scan) {
14165+ int obss_scan, bool dfs_enabled) {
14166 int chan_idx;
14167 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
14168 int i, res;
14169 unsigned int j;
14170 static const int ht40plus[] = {
14171+ 1, 2, 3, 4, 5, 6, 7,
14172 36, 44, 52, 60, 100, 108, 116, 124, 132, 140,
14173 149, 157, 165, 173, 184, 192
14174 };
14175@@ -2858,8 +2863,11 @@ static void ibss_mesh_select_40mhz(struct wpa_supplicant *wpa_s,
14176 return;
14177
14178 /* Check primary channel flags */
14179- if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
14180+ if (pri_chan->flag & HOSTAPD_CHAN_DISABLED)
14181 return;
14182+ if (pri_chan->flag & (HOSTAPD_CHAN_RADAR | HOSTAPD_CHAN_NO_IR))
14183+ if (!dfs_enabled)
14184+ return;
14185
14186 #ifdef CONFIG_HT_OVERRIDES
14187 if (ssid->disable_ht40)
14188@@ -2885,8 +2893,11 @@ static void ibss_mesh_select_40mhz(struct wpa_supplicant *wpa_s,
14189 return;
14190
14191 /* Check secondary channel flags */
14192- if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
14193+ if (sec_chan->flag & HOSTAPD_CHAN_DISABLED)
14194 return;
14195+ if (sec_chan->flag & (HOSTAPD_CHAN_RADAR | HOSTAPD_CHAN_NO_IR))
14196+ if (!dfs_enabled)
14197+ return;
14198
14199 if (ht40 == -1) {
14200 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
14201@@ -2941,7 +2952,7 @@ static bool ibss_mesh_select_80_160mhz(struct wpa_supplicant *wpa_s,
14202 const struct wpa_ssid *ssid,
14203 struct hostapd_hw_modes *mode,
14204 struct hostapd_freq_params *freq,
14205- int ieee80211_mode, bool is_6ghz) {
14206+ int ieee80211_mode, bool is_6ghz, bool dfs_enabled) {
14207 static const int bw80[] = {
14208 5180, 5260, 5500, 5580, 5660, 5745, 5825,
14209 5955, 6035, 6115, 6195, 6275, 6355, 6435,
14210@@ -2986,7 +2997,7 @@ static bool ibss_mesh_select_80_160mhz(struct wpa_supplicant *wpa_s,
14211 goto skip_80mhz;
14212
14213 /* Use 40 MHz if channel not usable */
14214- if (!ibss_mesh_is_80mhz_avail(channel, mode))
14215+ if (!ibss_mesh_is_80mhz_avail(channel, mode, dfs_enabled))
14216 goto skip_80mhz;
14217
14218 chwidth = CONF_OPER_CHWIDTH_80MHZ;
14219@@ -3000,7 +3011,7 @@ static bool ibss_mesh_select_80_160mhz(struct wpa_supplicant *wpa_s,
14220 if ((mode->he_capab[ieee80211_mode].phy_cap[
14221 HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
14222 HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G) && is_6ghz &&
14223- ibss_mesh_is_80mhz_avail(channel + 16, mode)) {
14224+ ibss_mesh_is_80mhz_avail(channel + 16, mode, dfs_enabled)) {
14225 for (j = 0; j < ARRAY_SIZE(bw160); j++) {
14226 if (freq->freq == bw160[j]) {
14227 chwidth = CONF_OPER_CHWIDTH_160MHZ;
14228@@ -3028,10 +3039,12 @@ static bool ibss_mesh_select_80_160mhz(struct wpa_supplicant *wpa_s,
14229 if (!chan)
14230 continue;
14231
14232- if (chan->flag & (HOSTAPD_CHAN_DISABLED |
14233- HOSTAPD_CHAN_NO_IR |
14234- HOSTAPD_CHAN_RADAR))
14235+ if (chan->flag & HOSTAPD_CHAN_DISABLED)
14236 continue;
14237+ if (chan->flag & (HOSTAPD_CHAN_RADAR |
14238+ HOSTAPD_CHAN_NO_IR))
14239+ if (!dfs_enabled)
14240+ continue;
14241
14242 /* Found a suitable second segment for 80+80 */
14243 chwidth = CONF_OPER_CHWIDTH_80P80MHZ;
14244@@ -3083,12 +3096,17 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
14245 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
14246 enum hostapd_hw_mode hw_mode;
14247 struct hostapd_hw_modes *mode = NULL;
14248- int i, obss_scan = 1;
14249+ int i, obss_scan = !(ssid->noscan);
14250 u8 channel;
14251 bool is_6ghz, is_24ghz;
14252+ bool dfs_enabled = wpa_s->conf->country[0] && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_RADAR);
14253
14254 freq->freq = ssid->frequency;
14255
14256+ if (ssid->fixed_freq) {
14257+ obss_scan = 0;
14258+ }
14259+
14260 if (ssid->mode == WPAS_MODE_IBSS && !ssid->fixed_freq) {
14261 struct wpa_bss *bss = ibss_find_existing_bss(wpa_s, ssid);
14262
14263@@ -3132,11 +3150,13 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
14264 freq->he_enabled = ibss_mesh_can_use_he(wpa_s, ssid, mode,
14265 ieee80211_mode);
14266 freq->channel = channel;
14267+ if (mode->mode == HOSTAPD_MODE_IEEE80211G && ssid->noscan)
14268+ ibss_mesh_select_40mhz(wpa_s, ssid, mode, freq, obss_scan, dfs_enabled);
14269 /* Setup higher BW only for 5 GHz */
14270 if (mode->mode == HOSTAPD_MODE_IEEE80211A) {
14271- ibss_mesh_select_40mhz(wpa_s, ssid, mode, freq, obss_scan);
14272+ ibss_mesh_select_40mhz(wpa_s, ssid, mode, freq, obss_scan, dfs_enabled);
14273 if (!ibss_mesh_select_80_160mhz(wpa_s, ssid, mode, freq,
14274- ieee80211_mode, is_6ghz))
14275+ ieee80211_mode, is_6ghz, dfs_enabled))
14276 freq->he_enabled = freq->vht_enabled = false;
14277 }
14278
14279@@ -4240,6 +4260,12 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
14280 params.beacon_int = ssid->beacon_int;
14281 else
14282 params.beacon_int = wpa_s->conf->beacon_int;
14283+ int i = 0;
14284+ while (i < WLAN_SUPP_RATES_MAX) {
14285+ params.rates[i] = ssid->rates[i];
14286+ i++;
14287+ }
14288+ params.mcast_rate = ssid->mcast_rate;
14289 }
14290
14291 if (bss && ssid->enable_edmg)
14292@@ -5861,7 +5887,7 @@ wpa_supplicant_alloc(struct wpa_supplicant *parent)
14293 if (wpa_s == NULL)
14294 return NULL;
14295 wpa_s->scan_req = INITIAL_SCAN_REQ;
14296- wpa_s->scan_interval = 5;
14297+ wpa_s->scan_interval = 1;
14298 wpa_s->new_connection = 1;
14299 wpa_s->parent = parent ? parent : wpa_s;
14300 wpa_s->p2pdev = wpa_s->parent;
14301@@ -7576,7 +7602,6 @@ struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
14302 return NULL;
14303 }
14304
14305-
14306 /**
14307 * wpa_supplicant_match_existing - Match existing interfaces
14308 * @global: Pointer to global data from wpa_supplicant_init()
14309@@ -7611,6 +7636,11 @@ static int wpa_supplicant_match_existing(struct wpa_global *global)
14310
14311 #endif /* CONFIG_MATCH_IFACE */
14312
14313+extern void supplicant_event(void *ctx, enum wpa_event_type event,
14314+ union wpa_event_data *data);
14315+
14316+extern void supplicant_event_global(void *ctx, enum wpa_event_type event,
14317+ union wpa_event_data *data);
14318
14319 /**
14320 * wpa_supplicant_add_iface - Add a new network interface
14321@@ -7693,6 +7723,9 @@ struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
14322 }
14323 #endif /* CONFIG_P2P */
14324
14325+ wpas_ubus_add_bss(wpa_s);
14326+ wpas_ucode_add_bss(wpa_s);
14327+
14328 return wpa_s;
14329 }
14330
14331@@ -7719,6 +7752,9 @@ int wpa_supplicant_remove_iface(struct wpa_global *global,
14332 struct wpa_supplicant *parent = wpa_s->parent;
14333 #endif /* CONFIG_MESH */
14334
14335+ wpas_ucode_free_bss(wpa_s);
14336+ wpas_ubus_free_bss(wpa_s);
14337+
14338 /* Remove interface from the global list of interfaces */
14339 prev = global->ifaces;
14340 if (prev == wpa_s) {
14341@@ -7867,6 +7903,8 @@ struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
14342 #ifndef CONFIG_NO_WPA_MSG
14343 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
14344 #endif /* CONFIG_NO_WPA_MSG */
14345+ wpa_supplicant_event = supplicant_event;
14346+ wpa_supplicant_event_global = supplicant_event_global;
14347
14348 if (params->wpa_debug_file_path)
14349 wpa_debug_open_file(params->wpa_debug_file_path);
14350@@ -8025,6 +8063,7 @@ struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
14351
14352 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
14353 wpas_periodic, global, NULL);
14354+ wpas_ucode_init(global);
14355
14356 return global;
14357 }
14358@@ -8097,6 +8136,8 @@ void wpa_supplicant_deinit(struct wpa_global *global)
14359
14360 wpas_notify_supplicant_deinitialized(global);
14361
14362+ wpas_ucode_free();
14363+
14364 eap_peer_unregister_methods();
14365 #ifdef CONFIG_AP
14366 eap_server_unregister_methods();
14367diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
14368index 426d077d2..e0c0e5b0c 100644
14369--- a/wpa_supplicant/wpa_supplicant_i.h
14370+++ b/wpa_supplicant/wpa_supplicant_i.h
14371@@ -21,6 +21,8 @@
14372 #include "config_ssid.h"
14373 #include "wmm_ac.h"
14374 #include "pasn/pasn_common.h"
14375+#include "ubus.h"
14376+#include "ucode.h"
14377
14378 extern const char *const wpa_supplicant_version;
14379 extern const char *const wpa_supplicant_license;
14380@@ -319,6 +321,8 @@ struct wpa_global {
14381 #endif /* CONFIG_WIFI_DISPLAY */
14382
14383 struct psk_list_entry *add_psk; /* From group formation */
14384+
14385+ struct ubus_object ubus_global;
14386 };
14387
14388
14389@@ -693,6 +697,8 @@ struct wpa_supplicant {
14390 unsigned char own_addr[ETH_ALEN];
14391 unsigned char perm_addr[ETH_ALEN];
14392 char ifname[100];
14393+ struct wpas_ubus_bss ubus;
14394+ struct wpas_ucode_bss ucode;
14395 #ifdef CONFIG_MATCH_IFACE
14396 int matched;
14397 #endif /* CONFIG_MATCH_IFACE */
14398diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c
14399index 8cd355f6b..136b06583 100644
14400--- a/wpa_supplicant/wps_supplicant.c
14401+++ b/wpa_supplicant/wps_supplicant.c
14402@@ -33,6 +33,7 @@
14403 #include "p2p/p2p.h"
14404 #include "p2p_supplicant.h"
14405 #include "wps_supplicant.h"
14406+#include "ubus.h"
14407
14408
14409 #ifndef WPS_PIN_SCAN_IGNORE_SEL_REG
14410@@ -401,6 +402,8 @@ static int wpa_supplicant_wps_cred(void *ctx,
14411 wpa_hexdump_key(MSG_DEBUG, "WPS: Received Credential attribute",
14412 cred->cred_attr, cred->cred_attr_len);
14413
14414+ wpas_ubus_notify(wpa_s, cred);
14415+
14416 if (wpa_s->conf->wps_cred_processing == 1)
14417 return 0;
14418
14419diff --git a/wpa_supplicant/wps_supplicant.h b/wpa_supplicant/wps_supplicant.h
14420index aae3f7cb5..30b4e9105 100644
14421--- a/wpa_supplicant/wps_supplicant.h
14422+++ b/wpa_supplicant/wps_supplicant.h
14423@@ -9,6 +9,7 @@
14424 #ifndef WPS_SUPPLICANT_H
14425 #define WPS_SUPPLICANT_H
14426
14427+struct wpa_bss;
14428 struct wpa_scan_results;
14429
14430 #ifdef CONFIG_WPS
14431@@ -16,8 +17,6 @@ struct wpa_scan_results;
14432 #include "wps/wps.h"
14433 #include "wps/wps_defs.h"
14434
14435-struct wpa_bss;
14436-
14437 struct wps_new_ap_settings {
14438 const char *ssid_hex;
14439 const char *auth;
14440--
144412.39.2
14442