summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2019-06-05 11:35:39 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2019-06-05 14:16:00 +0200
commit705e362ea5d6f711e987f5d370467b8873fc2255 (patch)
treebb2152c95b76783069419dcd1c24014ba0eb3a1b
parentAdd RTEMS-specific getcredhostuuid() (diff)
downloadrtems-libbsd-705e362ea5d6f711e987f5d370467b8873fc2255.tar.bz2
Update to FreeBSD stable/12 2019-06-05
Git mirror commit 78576620f2689e23144a1cf1bf55106cc6abe2b7.
m---------freebsd-org0
-rw-r--r--freebsd/contrib/tcpdump/tcpdump.c3
-rw-r--r--freebsd/contrib/wpa/src/ap/ap_config.h174
-rw-r--r--freebsd/contrib/wpa/src/ap/ap_drv_ops.c76
-rw-r--r--freebsd/contrib/wpa/src/ap/ap_drv_ops.h33
-rw-r--r--freebsd/contrib/wpa/src/ap/hostapd.h102
-rw-r--r--freebsd/contrib/wpa/src/ap/hs20.c88
-rw-r--r--freebsd/contrib/wpa/src/ap/hs20.h4
-rw-r--r--freebsd/contrib/wpa/src/ap/ieee802_11.h46
-rw-r--r--freebsd/contrib/wpa/src/ap/ieee802_11_auth.h3
-rw-r--r--freebsd/contrib/wpa/src/ap/ieee802_11_shared.c502
-rw-r--r--freebsd/contrib/wpa/src/ap/pmksa_cache_auth.h10
-rw-r--r--freebsd/contrib/wpa/src/ap/sta_info.h83
-rw-r--r--freebsd/contrib/wpa/src/ap/wpa_auth.c2255
-rw-r--r--freebsd/contrib/wpa/src/ap/wpa_auth.h308
-rw-r--r--freebsd/contrib/wpa/src/ap/wpa_auth_ft.c3692
-rw-r--r--freebsd/contrib/wpa/src/ap/wpa_auth_i.h117
-rw-r--r--freebsd/contrib/wpa/src/ap/wpa_auth_ie.h18
-rw-r--r--freebsd/contrib/wpa/src/common/ctrl_iface_common.c38
-rw-r--r--freebsd/contrib/wpa/src/common/ctrl_iface_common.h6
-rw-r--r--freebsd/contrib/wpa/src/common/defs.h94
-rw-r--r--freebsd/contrib/wpa/src/common/dpp.h505
-rw-r--r--freebsd/contrib/wpa/src/common/gas.c2
-rw-r--r--freebsd/contrib/wpa/src/common/gas.h3
-rw-r--r--freebsd/contrib/wpa/src/common/gas_server.h44
-rw-r--r--freebsd/contrib/wpa/src/common/hw_features_common.c197
-rw-r--r--freebsd/contrib/wpa/src/common/hw_features_common.h8
-rw-r--r--freebsd/contrib/wpa/src/common/ieee802_11_common.c676
-rw-r--r--freebsd/contrib/wpa/src/common/ieee802_11_common.h120
-rw-r--r--freebsd/contrib/wpa/src/common/ieee802_11_defs.h674
-rw-r--r--freebsd/contrib/wpa/src/common/ieee802_1x_defs.h86
-rw-r--r--freebsd/contrib/wpa/src/common/ocv.h40
-rw-r--r--freebsd/contrib/wpa/src/common/qca-vendor.h5230
-rw-r--r--freebsd/contrib/wpa/src/common/sae.h17
-rw-r--r--freebsd/contrib/wpa/src/common/version.h2
-rw-r--r--freebsd/contrib/wpa/src/common/wpa_common.c1109
-rw-r--r--freebsd/contrib/wpa/src/common/wpa_common.h161
-rw-r--r--freebsd/contrib/wpa/src/common/wpa_ctrl.h91
-rw-r--r--freebsd/contrib/wpa/src/crypto/aes-ctr.c28
-rw-r--r--freebsd/contrib/wpa/src/crypto/aes.h4
-rw-r--r--freebsd/contrib/wpa/src/crypto/aes_siv.h21
-rw-r--r--freebsd/contrib/wpa/src/crypto/aes_wrap.h4
-rw-r--r--freebsd/contrib/wpa/src/crypto/crypto.h73
-rw-r--r--freebsd/contrib/wpa/src/crypto/crypto_openssl.c498
-rw-r--r--freebsd/contrib/wpa/src/crypto/ms_funcs.c45
-rw-r--r--freebsd/contrib/wpa/src/crypto/ms_funcs.h8
-rw-r--r--freebsd/contrib/wpa/src/crypto/random.c77
-rw-r--r--freebsd/contrib/wpa/src/crypto/sha256-internal.c6
-rw-r--r--freebsd/contrib/wpa/src/crypto/sha384.h15
-rw-r--r--freebsd/contrib/wpa/src/crypto/sha512.h27
-rw-r--r--freebsd/contrib/wpa/src/crypto/tls.h53
-rw-r--r--freebsd/contrib/wpa/src/crypto/tls_internal.c54
-rw-r--r--freebsd/contrib/wpa/src/drivers/driver.h1028
-rw-r--r--freebsd/contrib/wpa/src/drivers/driver_bsd.c2
-rw-r--r--freebsd/contrib/wpa/src/drivers/driver_common.c45
-rw-r--r--freebsd/contrib/wpa/src/drivers/driver_ndis.c16
-rw-r--r--freebsd/contrib/wpa/src/drivers/driver_nl80211.h29
-rw-r--r--freebsd/contrib/wpa/src/drivers/driver_wired.c350
-rw-r--r--freebsd/contrib/wpa/src/drivers/driver_wired_common.c324
-rw-r--r--freebsd/contrib/wpa/src/drivers/driver_wired_common.h34
-rw-r--r--freebsd/contrib/wpa/src/drivers/drivers.c3
-rw-r--r--freebsd/contrib/wpa/src/eap_peer/eap.c368
-rw-r--r--freebsd/contrib/wpa/src/eap_peer/eap.h35
-rw-r--r--freebsd/contrib/wpa/src/eap_peer/eap_config.h111
-rw-r--r--freebsd/contrib/wpa/src/eap_peer/eap_i.h13
-rw-r--r--freebsd/contrib/wpa/src/eap_peer/eap_leap.c17
-rw-r--r--freebsd/contrib/wpa/src/eap_peer/eap_mschapv2.c28
-rw-r--r--freebsd/contrib/wpa/src/eap_peer/eap_peap.c103
-rw-r--r--freebsd/contrib/wpa/src/eap_peer/eap_proxy.h12
-rw-r--r--freebsd/contrib/wpa/src/eap_peer/eap_psk.c12
-rw-r--r--freebsd/contrib/wpa/src/eap_peer/eap_tls.c35
-rw-r--r--freebsd/contrib/wpa/src/eap_peer/eap_tls_common.c121
-rw-r--r--freebsd/contrib/wpa/src/eap_peer/eap_tls_common.h8
-rw-r--r--freebsd/contrib/wpa/src/eap_peer/eap_ttls.c92
-rw-r--r--freebsd/contrib/wpa/src/eapol_auth/eapol_auth_sm.h1
-rw-r--r--freebsd/contrib/wpa/src/eapol_supp/eapol_supp_sm.c126
-rw-r--r--freebsd/contrib/wpa/src/eapol_supp/eapol_supp_sm.h50
-rw-r--r--freebsd/contrib/wpa/src/fst/fst.h16
-rw-r--r--freebsd/contrib/wpa/src/fst/fst_ctrl_aux.h22
-rw-r--r--freebsd/contrib/wpa/src/l2_packet/l2_packet.h1
-rw-r--r--freebsd/contrib/wpa/src/p2p/p2p.h18
-rw-r--r--freebsd/contrib/wpa/src/radius/radius.h10
-rw-r--r--freebsd/contrib/wpa/src/rsn_supp/peerkey.c1157
-rw-r--r--freebsd/contrib/wpa/src/rsn_supp/peerkey.h82
-rw-r--r--freebsd/contrib/wpa/src/rsn_supp/pmksa_cache.c136
-rw-r--r--freebsd/contrib/wpa/src/rsn_supp/pmksa_cache.h45
-rw-r--r--freebsd/contrib/wpa/src/rsn_supp/preauth.c11
-rw-r--r--freebsd/contrib/wpa/src/rsn_supp/wpa.c2062
-rw-r--r--freebsd/contrib/wpa/src/rsn_supp/wpa.h81
-rw-r--r--freebsd/contrib/wpa/src/rsn_supp/wpa_ft.c375
-rw-r--r--freebsd/contrib/wpa/src/rsn_supp/wpa_i.h87
-rw-r--r--freebsd/contrib/wpa/src/rsn_supp/wpa_ie.c81
-rw-r--r--freebsd/contrib/wpa/src/rsn_supp/wpa_ie.h14
-rw-r--r--freebsd/contrib/wpa/src/tls/tlsv1_client.h3
-rw-r--r--freebsd/contrib/wpa/src/tls/tlsv1_server.h7
-rw-r--r--freebsd/contrib/wpa/src/utils/base64.c144
-rw-r--r--freebsd/contrib/wpa/src/utils/base64.h4
-rw-r--r--freebsd/contrib/wpa/src/utils/bitfield.c91
-rw-r--r--freebsd/contrib/wpa/src/utils/common.c57
-rw-r--r--freebsd/contrib/wpa/src/utils/common.h12
-rw-r--r--freebsd/contrib/wpa/src/utils/const_time.h191
-rw-r--r--freebsd/contrib/wpa/src/utils/eloop.c29
-rw-r--r--freebsd/contrib/wpa/src/utils/eloop.h8
-rw-r--r--freebsd/contrib/wpa/src/utils/list.h6
-rw-r--r--freebsd/contrib/wpa/src/utils/os.h12
-rw-r--r--freebsd/contrib/wpa/src/utils/os_unix.c25
-rw-r--r--freebsd/contrib/wpa/src/utils/uuid.c25
-rw-r--r--freebsd/contrib/wpa/src/utils/uuid.h1
-rw-r--r--freebsd/contrib/wpa/src/utils/wpa_debug.c34
-rw-r--r--freebsd/contrib/wpa/src/utils/wpa_debug.h3
-rw-r--r--freebsd/contrib/wpa/src/utils/wpabuf.c6
-rw-r--r--freebsd/contrib/wpa/src/wps/wps.c22
-rw-r--r--freebsd/contrib/wpa/src/wps/wps.h38
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_attr_build.c14
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_attr_parse.c11
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_attr_parse.h1
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_common.c17
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_defs.h3
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_dev_attr.c8
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_dev_attr.h1
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_enrollee.c14
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_i.h5
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_registrar.c99
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_upnp.c2
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/ap.h21
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/bss.c73
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/bss.h11
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/config.c505
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/config.h201
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/config_file.c218
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/config_ssid.h265
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/ctrl_iface.c1597
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/ctrl_iface_unix.c14
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/dbus/dbus_new.h69
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/dbus/dbus_old.h142
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/dpp_supplicant.h29
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/driver_i.h226
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/events.c1246
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/gas_query.c128
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/gas_query.h5
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/hs20_supplicant.c145
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/hs20_supplicant.h7
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/interworking.c168
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/interworking.h2
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/main.c17
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/notify.c137
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/notify.h17
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/offchannel.c5
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/op_classes.c389
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/p2p_supplicant.h9
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/rrm.c1577
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/scan.c391
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/sme.h19
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/wmm_ac.c16
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/wnm_sta.h18
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/wpa_supplicant.c2089
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h248
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/wpas_glue.c181
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/wpas_kay.h10
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/wps_supplicant.c38
-rw-r--r--freebsd/contrib/wpa/wpa_supplicant/wps_supplicant.h2
-rw-r--r--freebsd/crypto/openssl/apps/asn1pars.c14
-rw-r--r--freebsd/crypto/openssl/apps/cms.c3
-rw-r--r--freebsd/crypto/openssl/apps/enc.c4
-rw-r--r--freebsd/crypto/openssl/apps/ocsp.c11
-rw-r--r--freebsd/crypto/openssl/apps/s_cb.c106
-rw-r--r--freebsd/crypto/openssl/apps/s_client.c2
-rw-r--r--freebsd/crypto/openssl/apps/speed.c83
-rw-r--r--freebsd/crypto/openssl/crypto/bio/b_addr.c6
-rw-r--r--freebsd/crypto/openssl/crypto/bio/bss_mem.c41
-rw-r--r--freebsd/crypto/openssl/crypto/blake2/blake2b.c10
-rw-r--r--freebsd/crypto/openssl/crypto/bn/bn_ctx.c2
-rw-r--r--freebsd/crypto/openssl/crypto/bn/bn_lib.c2
-rw-r--r--freebsd/crypto/openssl/crypto/bn/bn_prime.c5
-rw-r--r--freebsd/crypto/openssl/crypto/conf/conf_sap.c1
-rw-r--r--freebsd/crypto/openssl/crypto/dh/dh_check.c28
-rw-r--r--freebsd/crypto/openssl/crypto/dh/dh_gen.c8
-rw-r--r--freebsd/crypto/openssl/crypto/dh/dh_key.c8
-rw-r--r--freebsd/crypto/openssl/crypto/dh/dh_pmeth.c4
-rw-r--r--freebsd/crypto/openssl/crypto/dsa/dsa_gen.c8
-rw-r--r--freebsd/crypto/openssl/crypto/dsa/dsa_ossl.c8
-rw-r--r--freebsd/crypto/openssl/crypto/dsa/dsa_pmeth.c16
-rw-r--r--freebsd/crypto/openssl/crypto/ec/curve25519.c3
-rw-r--r--freebsd/crypto/openssl/crypto/ec/curve448/curve448.c6
-rw-r--r--freebsd/crypto/openssl/crypto/ec/curve448/curve448_tables.c1840
-rw-r--r--freebsd/crypto/openssl/crypto/ec/curve448/curve448utils.h6
-rw-r--r--freebsd/crypto/openssl/crypto/ec/curve448/f_generic.c8
-rw-r--r--freebsd/crypto/openssl/crypto/ec/curve448/scalar.c20
-rw-r--r--freebsd/crypto/openssl/crypto/ec/ec2_oct.c11
-rw-r--r--freebsd/crypto/openssl/crypto/ec/ec2_smpl.c3
-rw-r--r--freebsd/crypto/openssl/crypto/ec/ec_ameth.c9
-rw-r--r--freebsd/crypto/openssl/crypto/ec/ec_lib.c5
-rw-r--r--freebsd/crypto/openssl/crypto/ec/ec_mult.c11
-rw-r--r--freebsd/crypto/openssl/crypto/ec/ec_pmeth.c8
-rw-r--r--freebsd/crypto/openssl/crypto/ec/ecdh_ossl.c7
-rw-r--r--freebsd/crypto/openssl/crypto/ec/ecp_nistp521.c11
-rw-r--r--freebsd/crypto/openssl/crypto/ec/ecp_nistz256.c3
-rw-r--r--freebsd/crypto/openssl/crypto/ec/ecp_smpl.c6
-rw-r--r--freebsd/crypto/openssl/crypto/err/err.c49
-rw-r--r--freebsd/crypto/openssl/crypto/evp/digest.c5
-rw-r--r--freebsd/crypto/openssl/crypto/evp/e_aes.c16
-rw-r--r--freebsd/crypto/openssl/crypto/evp/e_aria.c16
-rw-r--r--freebsd/crypto/openssl/crypto/evp/e_chacha20_poly1305.c6
-rw-r--r--freebsd/crypto/openssl/crypto/evp/p_lib.c7
-rw-r--r--freebsd/crypto/openssl/crypto/evp/p_open.c4
-rw-r--r--freebsd/crypto/openssl/crypto/hmac/hmac.c9
-rw-r--r--freebsd/crypto/openssl/crypto/include/internal/dso_conf.h4
-rw-r--r--freebsd/crypto/openssl/crypto/init.c16
-rw-r--r--freebsd/crypto/openssl/crypto/mips_arch.h4
-rw-r--r--freebsd/crypto/openssl/crypto/modes/ccm128.c4
-rw-r--r--freebsd/crypto/openssl/crypto/o_str.c27
-rw-r--r--freebsd/crypto/openssl/crypto/objects/obj_dat.h4
-rw-r--r--freebsd/crypto/openssl/crypto/ocsp/ocsp_ext.c6
-rw-r--r--freebsd/crypto/openssl/crypto/ocsp/ocsp_lib.c6
-rw-r--r--freebsd/crypto/openssl/crypto/pem/pem_sign.c4
-rw-r--r--freebsd/crypto/openssl/crypto/rand/drbg_lib.c6
-rw-r--r--freebsd/crypto/openssl/crypto/rand/rand_lib.c12
-rw-r--r--freebsd/crypto/openssl/crypto/rand/rand_unix.c29
-rw-r--r--freebsd/crypto/openssl/crypto/rand/randfile.c4
-rw-r--r--freebsd/crypto/openssl/crypto/rsa/rsa_ameth.c6
-rw-r--r--freebsd/crypto/openssl/crypto/rsa/rsa_gen.c5
-rw-r--r--freebsd/crypto/openssl/crypto/rsa/rsa_oaep.c48
-rw-r--r--freebsd/crypto/openssl/crypto/rsa/rsa_ossl.c16
-rw-r--r--freebsd/crypto/openssl/crypto/rsa/rsa_pk1.c46
-rw-r--r--freebsd/crypto/openssl/crypto/rsa/rsa_pmeth.c13
-rw-r--r--freebsd/crypto/openssl/crypto/rsa/rsa_ssl.c57
-rw-r--r--freebsd/crypto/openssl/crypto/rsa/rsa_x931g.c8
-rw-r--r--freebsd/crypto/openssl/crypto/sha/keccak1600.c50
-rw-r--r--freebsd/crypto/openssl/crypto/x509/x509_lu.c5
-rw-r--r--freebsd/crypto/openssl/crypto/x509v3/v3_genn.c6
-rw-r--r--freebsd/crypto/openssl/e_os.h11
-rw-r--r--freebsd/crypto/openssl/engines/e_padlock.c8
-rw-r--r--freebsd/crypto/openssl/include/internal/dsoerr.h9
-rw-r--r--freebsd/crypto/openssl/include/internal/refcount.h16
-rw-r--r--freebsd/crypto/openssl/include/internal/tsan_assist.h2
-rw-r--r--freebsd/crypto/openssl/include/openssl/err.h3
-rw-r--r--freebsd/crypto/openssl/include/openssl/evp.h1
-rw-r--r--freebsd/crypto/openssl/include/openssl/obj_mac.h2
-rw-r--r--freebsd/crypto/openssl/include/openssl/ocsp.h6
-rw-r--r--freebsd/crypto/openssl/include/openssl/opensslv.h6
-rw-r--r--freebsd/crypto/openssl/include/openssl/ssl.h2
-rw-r--r--freebsd/crypto/openssl/include/openssl/x509v3.h6
-rw-r--r--freebsd/crypto/openssl/ssl/ssl_lib.c7
-rw-r--r--freebsd/crypto/openssl/ssl/ssl_locl.h13
-rw-r--r--freebsd/crypto/openssl/ssl/statem/extensions.c2
-rw-r--r--freebsd/crypto/openssl/ssl/statem/extensions_clnt.c38
-rw-r--r--freebsd/crypto/openssl/ssl/statem/extensions_srvr.c6
-rw-r--r--freebsd/crypto/openssl/ssl/statem/statem_clnt.c5
-rw-r--r--freebsd/crypto/openssl/ssl/statem/statem_srvr.c4
-rw-r--r--freebsd/lib/libc/include/libc_private.h3
-rw-r--r--freebsd/lib/libc/net/getnameinfo.c6
-rw-r--r--freebsd/sbin/ifconfig/ifconfig.c59
-rw-r--r--freebsd/sbin/ifconfig/ifgre.c25
-rw-r--r--freebsd/sbin/pfctl/pfctl_optimize.c20
-rw-r--r--freebsd/sys/arm/ti/cpsw/if_cpsw.c18
-rw-r--r--freebsd/sys/cam/cam_periph.h1
-rw-r--r--freebsd/sys/cam/scsi/scsi_all.c114
-rw-r--r--freebsd/sys/cam/scsi/scsi_all.h5
-rw-r--r--freebsd/sys/dev/cadence/if_cgem.c10
-rw-r--r--freebsd/sys/dev/e1000/if_em.c16
-rw-r--r--freebsd/sys/dev/fdt/fdt_common.c3
-rw-r--r--freebsd/sys/dev/nvme/nvme.h14
-rw-r--r--freebsd/sys/dev/pci/pci.c95
-rw-r--r--freebsd/sys/dev/pci/pci_pci.c31
-rw-r--r--freebsd/sys/dev/pci/pcivar.h2
-rw-r--r--freebsd/sys/dev/rtwn/if_rtwn.c4
-rw-r--r--freebsd/sys/dev/rtwn/if_rtwnvar.h3
-rw-r--r--freebsd/sys/dev/sdhci/sdhci.c100
-rw-r--r--freebsd/sys/dev/sdhci/sdhci.h8
-rw-r--r--freebsd/sys/dev/usb/net/if_smsc.c144
-rw-r--r--freebsd/sys/dev/usb/net/if_urereg.h2
-rw-r--r--freebsd/sys/dev/usb/wlan/if_rsu.c5
-rw-r--r--freebsd/sys/dev/usb/wlan/if_rsureg.h3
-rw-r--r--freebsd/sys/dev/usb/wlan/if_rumvar.h2
-rw-r--r--freebsd/sys/dev/usb/wlan/if_run.c56
-rw-r--r--freebsd/sys/dev/usb/wlan/if_runvar.h2
-rw-r--r--freebsd/sys/dev/usb/wlan/if_uath.c2
-rw-r--r--freebsd/sys/dev/usb/wlan/if_uathvar.h3
-rw-r--r--freebsd/sys/dev/usb/wlan/if_upgtvar.h2
-rw-r--r--freebsd/sys/dev/usb/wlan/if_uralvar.h2
-rw-r--r--freebsd/sys/dev/usb/wlan/if_urtw.c50
-rw-r--r--freebsd/sys/dev/usb/wlan/if_urtwvar.h8
-rw-r--r--freebsd/sys/dev/usb/wlan/if_zydreg.h2
-rw-r--r--freebsd/sys/kern/init_main.c1
-rw-r--r--freebsd/sys/kern/kern_intr.c16
-rw-r--r--freebsd/sys/kern/kern_mib.c14
-rw-r--r--freebsd/sys/kern/subr_bus.c103
-rw-r--r--freebsd/sys/net/bpf.c12
-rw-r--r--freebsd/sys/net/bridgestp.c3
-rw-r--r--freebsd/sys/net/ethernet.h1
-rw-r--r--freebsd/sys/net/ieee_oui.h80
-rw-r--r--freebsd/sys/net/if.c80
-rw-r--r--freebsd/sys/net/if_bridge.c54
-rw-r--r--freebsd/sys/net/if_ethersubr.c38
-rw-r--r--freebsd/sys/net/if_gre.c153
-rw-r--r--freebsd/sys/net/if_gre.h66
-rw-r--r--freebsd/sys/net/if_lagg.c61
-rw-r--r--freebsd/sys/net/if_stf.c1
-rw-r--r--freebsd/sys/net/if_tap.c22
-rw-r--r--freebsd/sys/net/if_tun.c74
-rw-r--r--freebsd/sys/net/if_var.h3
-rw-r--r--freebsd/sys/net/iflib.h4
-rw-r--r--freebsd/sys/net/pfvar.h37
-rw-r--r--freebsd/sys/net/rtsock.c2
-rw-r--r--freebsd/sys/net80211/ieee80211_ht.c4
-rw-r--r--freebsd/sys/netinet/cc/cc_newreno.c7
-rw-r--r--freebsd/sys/netinet/if_ether.c6
-rw-r--r--freebsd/sys/netinet/in.c9
-rw-r--r--freebsd/sys/netinet/in_mcast.c96
-rw-r--r--freebsd/sys/netinet/in_pcb.c5
-rw-r--r--freebsd/sys/netinet/ip_fw.h7
-rw-r--r--freebsd/sys/netinet/ip_gre.c271
-rw-r--r--freebsd/sys/netinet/ip_icmp.c2
-rw-r--r--freebsd/sys/netinet/ip_input.c6
-rw-r--r--freebsd/sys/netinet/ip_output.c6
-rw-r--r--freebsd/sys/netinet/raw_ip.c55
-rw-r--r--freebsd/sys/netinet/sctp.h2
-rw-r--r--freebsd/sys/netinet/sctp_indata.c9
-rw-r--r--freebsd/sys/netinet/sctp_output.c83
-rw-r--r--freebsd/sys/netinet/sctp_pcb.c13
-rw-r--r--freebsd/sys/netinet/sctp_structs.h2
-rw-r--r--freebsd/sys/netinet/sctp_usrreq.c175
-rw-r--r--freebsd/sys/netinet/sctputil.c86
-rw-r--r--freebsd/sys/netinet/sctputil.h9
-rw-r--r--freebsd/sys/netinet/tcp_input.c47
-rw-r--r--freebsd/sys/netinet/tcp_output.c12
-rw-r--r--freebsd/sys/netinet/tcp_sack.c50
-rw-r--r--freebsd/sys/netinet/tcp_subr.c7
-rw-r--r--freebsd/sys/netinet/tcp_syncache.c34
-rw-r--r--freebsd/sys/netinet/tcp_timer.c10
-rw-r--r--freebsd/sys/netinet/tcp_timer.h4
-rw-r--r--freebsd/sys/netinet/tcp_timewait.c2
-rw-r--r--freebsd/sys/netinet6/in6.c22
-rw-r--r--freebsd/sys/netinet6/in6_ifattach.c9
-rw-r--r--freebsd/sys/netinet6/in6_mcast.c8
-rw-r--r--freebsd/sys/netinet6/in6_src.c4
-rw-r--r--freebsd/sys/netinet6/ip6_output.c7
-rw-r--r--freebsd/sys/netinet6/mld6.c2
-rw-r--r--freebsd/sys/netinet6/nd6.c12
-rw-r--r--freebsd/sys/netinet6/raw_ip6.c11
-rw-r--r--freebsd/sys/netipsec/xform_ah.c22
-rw-r--r--freebsd/sys/netipsec/xform_esp.c23
-rw-r--r--freebsd/sys/netpfil/pf/pf.c2
-rw-r--r--freebsd/sys/netpfil/pf/pf_ioctl.c12
-rw-r--r--freebsd/sys/netpfil/pf/pf_table.c226
-rw-r--r--freebsd/sys/opencrypto/cbc_mac.c3
-rw-r--r--freebsd/sys/powerpc/include/machine/spr.h2
-rw-r--r--freebsd/sys/sys/ata.h11
-rw-r--r--freebsd/sys/sys/bus.h7
-rw-r--r--freebsd/sys/sys/capsicum.h7
-rw-r--r--freebsd/sys/sys/ctype.h72
-rw-r--r--freebsd/sys/sys/libkern.h1
-rw-r--r--freebsd/sys/sys/random.h1
-rw-r--r--freebsd/sys/sys/seq.h2
-rw-r--r--freebsd/sys/sys/slicer.h2
-rw-r--r--freebsd/sys/sys/sysctl.h19
-rw-r--r--freebsd/sys/sys/systm.h5
-rw-r--r--freebsd/sys/sys/user.h1
-rw-r--r--freebsd/sys/sys/vnode.h1
-rw-r--r--freebsd/sys/x86/include/machine/bus.h4
-rw-r--r--freebsd/sys/x86/include/machine/pci_cfgreg.h9
-rw-r--r--freebsd/usr.bin/netstat/inet.c29
-rw-r--r--libbsd.py19
-rw-r--r--rtemsbsd/include/machine/rtems-bsd-kernel-namespace.h12
-rw-r--r--rtemsbsd/include/rtems/bsd/local/bus_if.h71
-rw-r--r--rtemsbsd/include/rtems/bsd/local/usbdevs.h5
-rw-r--r--rtemsbsd/include/rtems/bsd/local/usbdevs_data.h18
-rw-r--r--rtemsbsd/local/bus_if.c22
368 files changed, 34630 insertions, 7508 deletions
diff --git a/freebsd-org b/freebsd-org
-Subproject 43a38f188ca2e936ec78104c30ea3e24d9c1606
+Subproject 78576620f2689e23144a1cf1bf55106cc6abe2b
diff --git a/freebsd/contrib/tcpdump/tcpdump.c b/freebsd/contrib/tcpdump/tcpdump.c
index e3d57f1c..d48ad1b0 100644
--- a/freebsd/contrib/tcpdump/tcpdump.c
+++ b/freebsd/contrib/tcpdump/tcpdump.c
@@ -2204,7 +2204,8 @@ main(int argc, char **argv)
}
#ifdef HAVE_CAPSICUM
- cansandbox = (VFileName == NULL && zflag == NULL);
+ cansandbox = (VFileName == NULL && zflag == NULL &&
+ ndo->ndo_espsecret == NULL);
#ifdef HAVE_CASPER
cansandbox = (cansandbox && (ndo->ndo_nflag || capdns != NULL));
#else
diff --git a/freebsd/contrib/wpa/src/ap/ap_config.h b/freebsd/contrib/wpa/src/ap/ap_config.h
index 8c8f7e28..509677a4 100644
--- a/freebsd/contrib/wpa/src/ap/ap_config.h
+++ b/freebsd/contrib/wpa/src/ap/ap_config.h
@@ -42,6 +42,7 @@ struct mesh_conf {
#define MESH_CONF_SEC_AMPE BIT(2)
unsigned int security;
enum mfp_options ieee80211w;
+ int ocv;
unsigned int pairwise_cipher;
unsigned int group_cipher;
unsigned int mgmt_group_cipher;
@@ -122,6 +123,7 @@ struct hostapd_vlan {
int vlan_id; /* VLAN ID or -1 (VLAN_ID_WILDCARD) for wildcard entry */
struct vlan_description vlan_desc;
char ifname[IFNAMSIZ + 1];
+ char bridge[IFNAMSIZ + 1];
int configured;
int dynamic_vlan;
#ifdef CONFIG_FULL_DYNAMIC_VLAN
@@ -132,6 +134,7 @@ struct hostapd_vlan {
};
#define PMK_LEN 32
+#define KEYID_LEN 32
#define MIN_PASSPHRASE_LEN 8
#define MAX_PASSPHRASE_LEN 63
struct hostapd_sta_wpa_psk_short {
@@ -145,9 +148,11 @@ struct hostapd_sta_wpa_psk_short {
struct hostapd_wpa_psk {
struct hostapd_wpa_psk *next;
int group;
+ char keyid[KEYID_LEN];
u8 psk[PMK_LEN];
u8 addr[ETH_ALEN];
u8 p2p_dev_addr[ETH_ALEN];
+ int vlan_id;
};
struct hostapd_eap_user {
@@ -160,6 +165,8 @@ struct hostapd_eap_user {
} methods[EAP_MAX_METHODS];
u8 *password;
size_t password_len;
+ u8 *salt;
+ size_t salt_len; /* non-zero when password is salted */
int phase2;
int force_version;
unsigned int wildcard_prefix:1;
@@ -169,6 +176,7 @@ struct hostapd_eap_user {
unsigned int macacl:1;
int ttls_auth; /* EAP_TTLS_AUTH_* bitfield */
struct hostapd_radius_attr *accept_attr;
+ u32 t_c_timestamp;
};
struct hostapd_radius_attr {
@@ -201,6 +209,12 @@ struct hostapd_lang_string {
u8 name[252];
};
+struct hostapd_venue_url {
+ u8 venue_number;
+ u8 url_len;
+ u8 url[254];
+};
+
#define MAX_NAI_REALMS 10
#define MAX_NAI_REALMLEN 255
#define MAX_NAI_EAP_METHODS 5
@@ -224,6 +238,19 @@ struct anqp_element {
struct wpabuf *payload;
};
+struct fils_realm {
+ struct dl_list list;
+ u8 hash[2];
+ char realm[];
+};
+
+struct sae_password_entry {
+ struct sae_password_entry *next;
+ char *password;
+ char *identifier;
+ u8 peer_addr[ETH_ALEN];
+ int vlan_id;
+};
/**
* struct hostapd_bss_config - Per-BSS configuration
@@ -242,7 +269,8 @@ struct hostapd_bss_config {
int max_num_sta; /* maximum number of STAs in station table */
int dtim_period;
- int bss_load_update_period;
+ unsigned int bss_load_update_period;
+ unsigned int chan_util_avg_period;
int ieee802_1x; /* use IEEE 802.1X */
int eapol_version;
@@ -287,7 +315,7 @@ struct hostapd_bss_config {
char iapp_iface[IFNAMSIZ + 1]; /* interface used with IAPP broadcast
* frames */
- enum {
+ enum macaddr_acl {
ACCEPT_UNLESS_DENIED = 0,
DENY_UNLESS_ACCEPTED = 1,
USE_EXTERNAL_RADIUS_AUTH = 2
@@ -313,33 +341,46 @@ struct hostapd_bss_config {
/* dot11AssociationSAQueryRetryTimeout (in TUs) */
int assoc_sa_query_retry_timeout;
#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_OCV
+ int ocv; /* Operating Channel Validation */
+#endif /* CONFIG_OCV */
enum {
PSK_RADIUS_IGNORED = 0,
PSK_RADIUS_ACCEPTED = 1,
PSK_RADIUS_REQUIRED = 2
} wpa_psk_radius;
int wpa_pairwise;
+ int group_cipher; /* wpa_group value override from configuation */
int wpa_group;
int wpa_group_rekey;
+ int wpa_group_rekey_set;
int wpa_strict_rekey;
int wpa_gmk_rekey;
int wpa_ptk_rekey;
+ u32 wpa_group_update_count;
+ u32 wpa_pairwise_update_count;
+ int wpa_disable_eapol_key_retries;
int rsn_pairwise;
int rsn_preauth;
char *rsn_preauth_interfaces;
- int peerkey;
-#ifdef CONFIG_IEEE80211R
+#ifdef CONFIG_IEEE80211R_AP
/* IEEE 802.11r - Fast BSS Transition */
u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN];
u8 r1_key_holder[FT_R1KH_ID_LEN];
- u32 r0_key_lifetime;
+ u32 r0_key_lifetime; /* PMK-R0 lifetime seconds */
+ int rkh_pos_timeout;
+ int rkh_neg_timeout;
+ int rkh_pull_timeout; /* ms */
+ int rkh_pull_retries;
u32 reassociation_deadline;
struct ft_remote_r0kh *r0kh_list;
struct ft_remote_r1kh *r1kh_list;
int pmk_r1_push;
int ft_over_ds;
-#endif /* CONFIG_IEEE80211R */
+ int ft_psk_generate_local;
+ int r1_max_key_lifetime;
+#endif /* CONFIG_IEEE80211R_AP */
char *ctrl_interface; /* directory for UNIX domain sockets */
#ifndef CONFIG_NATIVE_WINDOWS
@@ -351,12 +392,17 @@ struct hostapd_bss_config {
char *server_cert;
char *private_key;
char *private_key_passwd;
+ char *check_cert_subject;
int check_crl;
+ int check_crl_strict;
+ unsigned int crl_reload_interval;
unsigned int tls_session_lifetime;
+ unsigned int tls_flags;
char *ocsp_stapling_response;
char *ocsp_stapling_response_multi;
char *dh_file;
char *openssl_ciphers;
+ char *openssl_ecdh_curves;
u8 *pac_opaque_encr_key;
u8 *eap_fast_a_id;
size_t eap_fast_a_id_len;
@@ -419,9 +465,11 @@ struct hostapd_bss_config {
u8 *extra_cred;
size_t extra_cred_len;
int wps_cred_processing;
+ int wps_cred_add_sae;
int force_per_enrollee_psk;
u8 *ap_settings;
size_t ap_settings_len;
+ struct hostapd_ssid multi_ap_backhaul_ssid;
char *upnp_iface;
char *friendly_name;
char *manufacturer_url;
@@ -464,6 +512,7 @@ struct hostapd_bss_config {
int time_advertisement;
char *time_zone;
int wnm_sleep_mode;
+ int wnm_sleep_mode_no_keys;
int bss_transition;
/* IEEE 802.11u - Interworking */
@@ -486,6 +535,10 @@ struct hostapd_bss_config {
unsigned int venue_name_count;
struct hostapd_lang_string *venue_name;
+ /* Venue URL duples */
+ unsigned int venue_url_count;
+ struct hostapd_venue_url *venue_url;
+
/* IEEE 802.11u - Network Authentication Type */
u8 *network_auth_type;
size_t network_auth_type_len;
@@ -508,7 +561,7 @@ struct hostapd_bss_config {
struct dl_list anqp_elem; /* list of struct anqp_element */
u16 gas_comeback_delay;
- int gas_frag_limit;
+ size_t gas_frag_limit;
int gas_address3;
u8 qos_map_set[16 + 2 * 21];
@@ -519,6 +572,7 @@ struct hostapd_bss_config {
int na_mcast_to_ucast;
#ifdef CONFIG_HS20
int hs20;
+ int hs20_release;
int disable_dgaf;
u16 anqp_domain_id;
unsigned int hs20_oper_friendly_name_count;
@@ -547,13 +601,21 @@ struct hostapd_bss_config {
char **icons;
size_t icons_count;
char *osu_nai;
+ char *osu_nai2;
unsigned int service_desc_count;
struct hostapd_lang_string *service_desc;
} *hs20_osu_providers, *last_osu;
size_t hs20_osu_providers_count;
+ size_t hs20_osu_providers_nai_count;
+ char **hs20_operator_icon;
+ size_t hs20_operator_icon_count;
unsigned int hs20_deauth_req_timeout;
char *subscr_remediation_url;
u8 subscr_remediation_method;
+ char *hs20_sim_provisioning_url;
+ char *t_c_filename;
+ u32 t_c_timestamp;
+ char *t_c_server_url;
#endif /* CONFIG_HS20 */
u8 wps_rf_bands; /* RF bands for WPS (WPS_RF_*) */
@@ -566,7 +628,10 @@ struct hostapd_bss_config {
struct wpabuf *assocresp_elements;
unsigned int sae_anti_clogging_threshold;
+ unsigned int sae_sync;
+ int sae_require_mfp;
int *sae_groups;
+ struct sae_password_entry *sae_passwords;
char *wowlan_triggers; /* Wake-on-WLAN triggers */
@@ -574,6 +639,8 @@ struct hostapd_bss_config {
u8 bss_load_test[5];
u8 bss_load_test_set;
struct wpabuf *own_ie_override;
+ int sae_reflection_attack;
+ struct wpabuf *sae_commit_override;
#endif /* CONFIG_TESTING_OPTIONS */
#define MESH_ENABLED BIT(0)
@@ -591,12 +658,77 @@ struct hostapd_bss_config {
#ifdef CONFIG_MBO
int mbo_enabled;
+ /**
+ * oce - Enable OCE in AP and/or STA-CFON mode
+ * - BIT(0) is Reserved
+ * - Set BIT(1) to enable OCE in STA-CFON mode
+ * - Set BIT(2) to enable OCE in AP mode
+ */
+ unsigned int oce;
+ int mbo_cell_data_conn_pref;
#endif /* CONFIG_MBO */
int ftm_responder;
int ftm_initiator;
+
+#ifdef CONFIG_FILS
+ u8 fils_cache_id[FILS_CACHE_ID_LEN];
+ int fils_cache_id_set;
+ struct dl_list fils_realms; /* list of struct fils_realm */
+ int fils_dh_group;
+ struct hostapd_ip_addr dhcp_server;
+ int dhcp_rapid_commit_proxy;
+ unsigned int fils_hlp_wait_time;
+ u16 dhcp_server_port;
+ u16 dhcp_relay_port;
+#endif /* CONFIG_FILS */
+
+ int multicast_to_unicast;
+
+ int broadcast_deauth;
+
+#ifdef CONFIG_DPP
+ char *dpp_connector;
+ struct wpabuf *dpp_netaccesskey;
+ unsigned int dpp_netaccesskey_expiry;
+ struct wpabuf *dpp_csign;
+#endif /* CONFIG_DPP */
+
+#ifdef CONFIG_OWE
+ macaddr owe_transition_bssid;
+ u8 owe_transition_ssid[SSID_MAX_LEN];
+ size_t owe_transition_ssid_len;
+ char owe_transition_ifname[IFNAMSIZ + 1];
+ int *owe_groups;
+#endif /* CONFIG_OWE */
+
+ int coloc_intf_reporting;
+
+ u8 send_probe_response;
+
+#define BACKHAUL_BSS 1
+#define FRONTHAUL_BSS 2
+ int multi_ap; /* bitmap of BACKHAUL_BSS, FRONTHAUL_BSS */
};
+/**
+ * struct he_phy_capabilities_info - HE PHY capabilities
+ */
+struct he_phy_capabilities_info {
+ Boolean he_su_beamformer;
+ Boolean he_su_beamformee;
+ Boolean he_mu_beamformer;
+};
+
+/**
+ * struct he_operation - HE operation
+ */
+struct he_operation {
+ u8 he_bss_color;
+ u8 he_default_pe_duration;
+ u8 he_twt_required;
+ u8 he_rts_threshold;
+};
/**
* struct hostapd_config - Per-radio interface configuration
@@ -608,10 +740,10 @@ struct hostapd_config {
u16 beacon_int;
int rts_threshold;
int fragm_threshold;
- u8 send_probe_response;
u8 channel;
u8 acs;
struct wpa_freq_range_list acs_ch_list;
+ int acs_exclude_dfs;
enum hostapd_hw_mode hw_mode; /* HOSTAPD_MODE_IEEE80211A, .. */
enum {
LONG_PREAMBLE = 0,
@@ -620,6 +752,8 @@ struct hostapd_config {
int *supported_rates;
int *basic_rates;
+ unsigned int beacon_rate;
+ enum beacon_rate_type rate_type;
const struct wpa_driver_ops *driver;
char *driver_params;
@@ -635,6 +769,9 @@ struct hostapd_config {
* ' ' (ascii 32): all environments
* 'O': Outdoor environemnt only
* 'I': Indoor environment only
+ * 'X': Used with noncountry entity ("XXX")
+ * 0x00..0x31: identifying IEEE 802.11 standard
+ * Annex E table (0x04 = global table)
*/
int ieee80211d;
@@ -675,6 +812,7 @@ struct hostapd_config {
u8 vht_oper_chwidth;
u8 vht_oper_centr_freq_seg0_idx;
u8 vht_oper_centr_freq_seg1_idx;
+ u8 ht40_plus_minus_allowed;
/* Use driver-generated interface addresses when adding multiple BSSs */
u8 use_driver_iface_addr;
@@ -707,6 +845,22 @@ struct hostapd_config {
struct wpabuf *lci;
struct wpabuf *civic;
+ int stationary_ap;
+
+ int ieee80211ax;
+#ifdef CONFIG_IEEE80211AX
+ struct he_phy_capabilities_info he_phy_capab;
+ struct he_operation he_op;
+ struct ieee80211_he_mu_edca_parameter_set he_mu_edca;
+#endif /* CONFIG_IEEE80211AX */
+
+ /* VHT enable/disable config from CHAN_SWITCH */
+#define CH_SWITCH_VHT_ENABLED BIT(0)
+#define CH_SWITCH_VHT_DISABLED BIT(1)
+ unsigned int ch_switch_vht_config;
+
+ int rssi_reject_assoc_rssi;
+ int rssi_reject_assoc_timeout;
};
@@ -714,6 +868,7 @@ int hostapd_mac_comp(const void *a, const void *b);
struct hostapd_config * hostapd_config_defaults(void);
void hostapd_config_defaults_bss(struct hostapd_bss_config *bss);
void hostapd_config_free_eap_user(struct hostapd_eap_user *user);
+void hostapd_config_free_eap_users(struct hostapd_eap_user *user);
void hostapd_config_clear_wpa_psk(struct hostapd_wpa_psk **p);
void hostapd_config_free_bss(struct hostapd_bss_config *conf);
void hostapd_config_free(struct hostapd_config *conf);
@@ -722,7 +877,7 @@ int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
int hostapd_rate_found(int *list, int rate);
const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
const u8 *addr, const u8 *p2p_dev_addr,
- const u8 *prev_psk);
+ const u8 *prev_psk, int *vlan_id);
int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf);
int hostapd_vlan_valid(struct hostapd_vlan *vlan,
struct vlan_description *vlan_desc);
@@ -733,5 +888,6 @@ hostapd_config_get_radius_attr(struct hostapd_radius_attr *attr, u8 type);
int hostapd_config_check(struct hostapd_config *conf, int full_config);
void hostapd_set_security_params(struct hostapd_bss_config *bss,
int full_config);
+int hostapd_sae_pw_id_in_use(struct hostapd_bss_config *conf);
#endif /* HOSTAPD_CONFIG_H */
diff --git a/freebsd/contrib/wpa/src/ap/ap_drv_ops.c b/freebsd/contrib/wpa/src/ap/ap_drv_ops.c
index c0111c37..09a61882 100644
--- a/freebsd/contrib/wpa/src/ap/ap_drv_ops.c
+++ b/freebsd/contrib/wpa/src/ap/ap_drv_ops.c
@@ -21,6 +21,7 @@
#include "ap_config.h"
#include "p2p_hostapd.h"
#include "hs20.h"
+#include "wpa_auth.h"
#include "ap_drv_ops.h"
@@ -101,6 +102,13 @@ int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
goto fail;
#endif /* CONFIG_FST */
+#ifdef CONFIG_FILS
+ pos = hostapd_eid_fils_indic(hapd, buf, 0);
+ if (add_buf_data(&beacon, buf, pos - buf) < 0 ||
+ add_buf_data(&proberesp, buf, pos - buf) < 0)
+ goto fail;
+#endif /* CONFIG_FILS */
+
if (add_buf(&beacon, hapd->wps_beacon_ie) < 0 ||
add_buf(&proberesp, hapd->wps_probe_resp_ie) < 0)
goto fail;
@@ -170,7 +178,8 @@ int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
#endif /* CONFIG_HS20 */
#ifdef CONFIG_MBO
- if (hapd->conf->mbo_enabled) {
+ if (hapd->conf->mbo_enabled ||
+ OCE_STA_CFON_ENABLED(hapd) || OCE_AP_ENABLED(hapd)) {
pos = hostapd_eid_mbo(hapd, buf, sizeof(buf));
if (add_buf_data(&beacon, buf, pos - buf) < 0 ||
add_buf_data(&proberesp, buf, pos - buf) < 0 ||
@@ -179,6 +188,13 @@ int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
}
#endif /* CONFIG_MBO */
+#ifdef CONFIG_OWE
+ pos = hostapd_eid_owe_trans(hapd, buf, sizeof(buf));
+ if (add_buf_data(&beacon, buf, pos - buf) < 0 ||
+ add_buf_data(&proberesp, buf, pos - buf) < 0)
+ goto fail;
+#endif /* CONFIG_OWE */
+
add_buf(&beacon, hapd->conf->vendor_elements);
add_buf(&proberesp, hapd->conf->vendor_elements);
add_buf(&assocresp, hapd->conf->assocresp_elements);
@@ -342,10 +358,44 @@ int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr,
int hostapd_sta_auth(struct hostapd_data *hapd, const u8 *addr,
u16 seq, u16 status, const u8 *ie, size_t len)
{
+ struct wpa_driver_sta_auth_params params;
+#ifdef CONFIG_FILS
+ struct sta_info *sta;
+#endif /* CONFIG_FILS */
+
if (hapd->driver == NULL || hapd->driver->sta_auth == NULL)
return 0;
- return hapd->driver->sta_auth(hapd->drv_priv, hapd->own_addr, addr,
- seq, status, ie, len);
+
+ os_memset(&params, 0, sizeof(params));
+
+#ifdef CONFIG_FILS
+ sta = ap_get_sta(hapd, addr);
+ if (!sta) {
+ wpa_printf(MSG_DEBUG, "Station " MACSTR
+ " not found for sta_auth processing",
+ MAC2STR(addr));
+ return 0;
+ }
+
+ if (sta->auth_alg == WLAN_AUTH_FILS_SK ||
+ sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
+ sta->auth_alg == WLAN_AUTH_FILS_PK) {
+ params.fils_auth = 1;
+ wpa_auth_get_fils_aead_params(sta->wpa_sm, params.fils_anonce,
+ params.fils_snonce,
+ params.fils_kek,
+ &params.fils_kek_len);
+ }
+#endif /* CONFIG_FILS */
+
+ params.own_addr = hapd->own_addr;
+ params.addr = addr;
+ params.seq = seq;
+ params.status = status;
+ params.ie = ie;
+ params.len = len;
+
+ return hapd->driver->sta_auth(hapd->drv_priv, &params);
}
@@ -556,13 +606,13 @@ int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs,
struct hostapd_hw_modes *
hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes,
- u16 *flags)
+ u16 *flags, u8 *dfs_domain)
{
if (hapd->driver == NULL ||
hapd->driver->get_hw_feature_data == NULL)
return NULL;
return hapd->driver->get_hw_feature_data(hapd->drv_priv, num_modes,
- flags);
+ flags, dfs_domain);
}
@@ -696,6 +746,15 @@ int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq,
sta = ap_get_sta(hapd, dst);
if (!sta || !(sta->flags & WLAN_STA_ASSOC))
bssid = wildcard_bssid;
+ } else if (is_broadcast_ether_addr(dst) &&
+ len > 0 && data[0] == WLAN_ACTION_PUBLIC) {
+ /*
+ * The only current use case of Public Action frames with
+ * broadcast destination address is DPP PKEX. That case is
+ * directing all devices and not just the STAs within the BSS,
+ * so have to use the wildcard BSSID value.
+ */
+ bssid = wildcard_bssid;
}
return hapd->driver->send_action(hapd->drv_priv, freq, wait, dst,
hapd->own_addr, bssid, data, len, 0);
@@ -776,7 +835,9 @@ static void hostapd_get_hw_mode_any_channels(struct hostapd_data *hapd,
if ((acs_ch_list_all ||
freq_range_list_includes(&hapd->iface->conf->acs_ch_list,
chan->chan)) &&
- !(chan->flag & HOSTAPD_CHAN_DISABLED))
+ !(chan->flag & HOSTAPD_CHAN_DISABLED) &&
+ !(hapd->iface->conf->acs_exclude_dfs &&
+ (chan->flag & HOSTAPD_CHAN_RADAR)))
int_array_add_unique(freq_list, chan->freq);
}
}
@@ -831,6 +892,9 @@ int hostapd_drv_do_acs(struct hostapd_data *hapd)
&hapd->iface->conf->acs_ch_list,
chan->chan))
continue;
+ if (hapd->iface->conf->acs_exclude_dfs &&
+ (chan->flag & HOSTAPD_CHAN_RADAR))
+ continue;
if (!(chan->flag & HOSTAPD_CHAN_DISABLED)) {
channels[num_channels++] = chan->chan;
int_array_add_unique(&freq_list, chan->freq);
diff --git a/freebsd/contrib/wpa/src/ap/ap_drv_ops.h b/freebsd/contrib/wpa/src/ap/ap_drv_ops.h
index 0bb7954e..de40171e 100644
--- a/freebsd/contrib/wpa/src/ap/ap_drv_ops.h
+++ b/freebsd/contrib/wpa/src/ap/ap_drv_ops.h
@@ -72,7 +72,7 @@ int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs,
int cw_min, int cw_max, int burst_time);
struct hostapd_hw_modes *
hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes,
- u16 *flags);
+ u16 *flags, u8 *dfs_domain);
int hostapd_driver_commit(struct hostapd_data *hapd);
int hostapd_drv_none(struct hostapd_data *hapd);
int hostapd_driver_scan(struct hostapd_data *hapd,
@@ -103,6 +103,14 @@ int hostapd_drv_send_action_addr3_ap(struct hostapd_data *hapd,
unsigned int freq,
unsigned int wait, const u8 *dst,
const u8 *data, size_t len);
+static inline void
+hostapd_drv_send_action_cancel_wait(struct hostapd_data *hapd)
+{
+ if (!hapd->driver || !hapd->driver->send_action_cancel_wait ||
+ !hapd->drv_priv)
+ return;
+ hapd->driver->send_action_cancel_wait(hapd->drv_priv);
+}
int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr,
u16 auth_alg);
int hostapd_sta_auth(struct hostapd_data *hapd, const u8 *addr,
@@ -274,8 +282,9 @@ static inline const char * hostapd_drv_get_radio_name(struct hostapd_data *hapd)
static inline int hostapd_drv_switch_channel(struct hostapd_data *hapd,
struct csa_settings *settings)
{
- if (hapd->driver == NULL || hapd->driver->switch_channel == NULL)
- return -ENOTSUP;
+ if (hapd->driver == NULL || hapd->driver->switch_channel == NULL ||
+ hapd->drv_priv == NULL)
+ return -1;
return hapd->driver->switch_channel(hapd->drv_priv, settings);
}
@@ -347,4 +356,22 @@ static inline int hostapd_drv_stop_ap(struct hostapd_data *hapd)
return hapd->driver->stop_ap(hapd->drv_priv);
}
+static inline int hostapd_drv_channel_info(struct hostapd_data *hapd,
+ struct wpa_channel_info *ci)
+{
+ if (!hapd->driver || !hapd->driver->channel_info)
+ return -1;
+ return hapd->driver->channel_info(hapd->drv_priv, ci);
+}
+
+static inline int
+hostapd_drv_send_external_auth_status(struct hostapd_data *hapd,
+ struct external_auth *params)
+{
+ if (!hapd->driver || !hapd->drv_priv ||
+ !hapd->driver->send_external_auth_status)
+ return -1;
+ return hapd->driver->send_external_auth_status(hapd->drv_priv, params);
+}
+
#endif /* AP_DRV_OPS */
diff --git a/freebsd/contrib/wpa/src/ap/hostapd.h b/freebsd/contrib/wpa/src/ap/hostapd.h
index dec46f69..790d3775 100644
--- a/freebsd/contrib/wpa/src/ap/hostapd.h
+++ b/freebsd/contrib/wpa/src/ap/hostapd.h
@@ -14,6 +14,13 @@
#include "ap_config.h"
#include "drivers/driver.h"
+#define OCE_STA_CFON_ENABLED(hapd) \
+ ((hapd->conf->oce & OCE_STA_CFON) && \
+ (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON))
+#define OCE_AP_ENABLED(hapd) \
+ ((hapd->conf->oce & OCE_AP) && \
+ (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_OCE_AP))
+
struct wpa_ctrl_dst;
struct radius_server_data;
struct upnp_wps_device_sm;
@@ -53,7 +60,14 @@ struct hapd_interfaces {
#ifndef CONFIG_NO_VLAN
struct dynamic_iface *vlan_priv;
#endif /* CONFIG_NO_VLAN */
+#ifdef CONFIG_ETH_P_OUI
+ struct dl_list eth_p_oui; /* OUI Extended EtherType handlers */
+#endif /* CONFIG_ETH_P_OUI */
int eloop_initialized;
+
+#ifdef CONFIG_DPP
+ struct dpp_global *dpp;
+#endif /* CONFIG_DPP */
};
enum hostapd_chan_status {
@@ -76,6 +90,7 @@ struct hostapd_rate_data {
};
struct hostapd_frame_info {
+ unsigned int freq;
u32 channel;
u32 datarate;
int ssi_signal; /* dBm */
@@ -109,6 +124,14 @@ struct hostapd_neighbor_entry {
struct wpabuf *civic;
/* LCI update time */
struct os_time lci_date;
+ int stationary;
+};
+
+struct hostapd_sae_commit_queue {
+ struct dl_list list;
+ int rssi;
+ size_t len;
+ u8 msg[];
};
/**
@@ -184,6 +207,17 @@ struct hostapd_data {
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
struct l2_packet_data *l2;
+
+#ifdef CONFIG_IEEE80211R_AP
+ struct dl_list l2_queue;
+ struct dl_list l2_oui_queue;
+ struct eth_p_oui_ctx *oui_pull;
+ struct eth_p_oui_ctx *oui_resp;
+ struct eth_p_oui_ctx *oui_push;
+ struct eth_p_oui_ctx *oui_sreq;
+ struct eth_p_oui_ctx *oui_sresp;
+#endif /* CONFIG_IEEE80211R_AP */
+
struct wps_context *wps;
int beacon_set_done;
@@ -242,9 +276,6 @@ struct hostapd_data {
unsigned int cs_c_off_ecsa_beacon;
unsigned int cs_c_off_ecsa_proberesp;
- /* BSS Load */
- unsigned int bss_load_update_timeout;
-
#ifdef CONFIG_P2P
struct p2p_data *p2p;
struct p2p_group *p2p_group;
@@ -259,9 +290,6 @@ struct hostapd_data {
int noa_start;
int noa_duration;
#endif /* CONFIG_P2P */
-#ifdef CONFIG_INTERWORKING
- size_t gas_frag_limit;
-#endif /* CONFIG_INTERWORKING */
#ifdef CONFIG_PROXYARP
struct l2_packet_data *sock_dhcp;
struct l2_packet_data *sock_ndisc;
@@ -284,7 +312,10 @@ struct hostapd_data {
/** Key used for generating SAE anti-clogging tokens */
u8 sae_token_key[8];
struct os_reltime last_sae_token_key_update;
+ u16 sae_token_idx;
+ u16 sae_pending_token_idx[256];
int dot11RSNASAERetransPeriod; /* msec */
+ struct dl_list sae_commit_queue; /* struct hostapd_sae_commit_queue */
#endif /* CONFIG_SAE */
#ifdef CONFIG_TESTING_OPTIONS
@@ -292,6 +323,18 @@ struct hostapd_data {
unsigned int ext_eapol_frame_io:1;
struct l2_packet_data *l2_test;
+
+ enum wpa_alg last_gtk_alg;
+ int last_gtk_key_idx;
+ u8 last_gtk[WPA_GTK_MAX_LEN];
+ size_t last_gtk_len;
+
+#ifdef CONFIG_IEEE80211W
+ enum wpa_alg last_igtk_alg;
+ int last_igtk_key_idx;
+ u8 last_igtk[WPA_IGTK_MAX_LEN];
+ size_t last_igtk_len;
+#endif /* CONFIG_IEEE80211W */
#endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_MBO
@@ -300,10 +343,42 @@ struct hostapd_data {
struct dl_list nr_db;
+ u8 beacon_req_token;
u8 lci_req_token;
u8 range_req_token;
unsigned int lci_req_active:1;
unsigned int range_req_active:1;
+
+ int dhcp_sock; /* UDP socket used with the DHCP server */
+
+#ifdef CONFIG_DPP
+ int dpp_init_done;
+ struct dpp_authentication *dpp_auth;
+ u8 dpp_allowed_roles;
+ int dpp_qr_mutual;
+ int dpp_auth_ok_on_ack;
+ int dpp_in_response_listen;
+ struct gas_query_ap *gas;
+ struct dpp_pkex *dpp_pkex;
+ struct dpp_bootstrap_info *dpp_pkex_bi;
+ char *dpp_pkex_code;
+ char *dpp_pkex_identifier;
+ char *dpp_pkex_auth_cmd;
+ char *dpp_configurator_params;
+ struct os_reltime dpp_last_init;
+ struct os_reltime dpp_init_iter_start;
+ unsigned int dpp_init_max_tries;
+ unsigned int dpp_init_retry_time;
+ unsigned int dpp_resp_wait_time;
+ unsigned int dpp_resp_max_tries;
+ unsigned int dpp_resp_retry_time;
+#ifdef CONFIG_TESTING_OPTIONS
+ char *dpp_config_obj_override;
+ char *dpp_discovery_override;
+ char *dpp_groups_override;
+ unsigned int dpp_ignore_netaccesskey_mismatch:1;
+#endif /* CONFIG_TESTING_OPTIONS */
+#endif /* CONFIG_DPP */
};
@@ -311,6 +386,7 @@ struct hostapd_sta_info {
struct dl_list list;
u8 addr[ETH_ALEN];
struct os_reltime last_seen;
+ int ssi_signal;
#ifdef CONFIG_TAXONOMY
struct wpabuf *probe_ie_taxonomy;
#endif /* CONFIG_TAXONOMY */
@@ -440,6 +516,10 @@ struct hostapd_iface {
u64 last_channel_time_busy;
u8 channel_utilization;
+ unsigned int chan_util_samples_sum;
+ unsigned int chan_util_num_sample_periods;
+ unsigned int chan_util_average;
+
/* eCSA IE will be added only if operating class is specified */
u8 cs_oper_class;
@@ -459,6 +539,8 @@ struct hostapd_iface {
struct dl_list sta_seen; /* struct hostapd_sta_info */
unsigned int num_sta_seen;
+
+ u8 dfs_domain;
};
/* hostapd.c */
@@ -466,6 +548,7 @@ int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
int (*cb)(struct hostapd_iface *iface,
void *ctx), void *ctx);
int hostapd_reload_config(struct hostapd_iface *iface);
+void hostapd_reconfig_encryption(struct hostapd_data *hapd);
struct hostapd_data *
hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface,
struct hostapd_config *conf,
@@ -492,6 +575,7 @@ void hostapd_channel_list_updated(struct hostapd_iface *iface, int initiator);
void hostapd_set_state(struct hostapd_iface *iface, enum hostapd_iface_state s);
const char * hostapd_state_text(enum hostapd_iface_state s);
int hostapd_csa_in_progress(struct hostapd_iface *iface);
+void hostapd_chan_switch_vht_config(struct hostapd_data *hapd, int vht_enabled);
int hostapd_switch_channel(struct hostapd_data *hapd,
struct csa_settings *settings);
void
@@ -499,6 +583,7 @@ hostapd_switch_channel_fallback(struct hostapd_iface *iface,
const struct hostapd_freq_params *freq_params);
void hostapd_cleanup_cs_params(struct hostapd_data *hapd);
void hostapd_periodic_iface(struct hostapd_iface *iface);
+int hostapd_owe_trans_get_info(struct hostapd_data *hapd);
/* utils.c */
int hostapd_register_probereq_cb(struct hostapd_data *hapd,
@@ -510,6 +595,8 @@ int hostapd_register_probereq_cb(struct hostapd_data *hapd,
void hostapd_prune_associations(struct hostapd_data *hapd, const u8 *addr);
/* drv_callbacks.c (TODO: move to somewhere else?) */
+void hostapd_notify_assoc_fils_finish(struct hostapd_data *hapd,
+ struct sta_info *sta);
int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
const u8 *ie, size_t ielen, int reassoc);
void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr);
@@ -533,6 +620,9 @@ hostapd_get_eap_user(struct hostapd_data *hapd, const u8 *identity,
struct hostapd_data * hostapd_get_iface(struct hapd_interfaces *interfaces,
const char *ifname);
+void hostapd_event_sta_opmode_changed(struct hostapd_data *hapd, const u8 *addr,
+ enum smps_mode smps_mode,
+ enum chan_width chan_width, u8 rx_nss);
#ifdef CONFIG_FST
void fst_hostapd_fill_iface_obj(struct hostapd_data *hapd,
diff --git a/freebsd/contrib/wpa/src/ap/hs20.c b/freebsd/contrib/wpa/src/ap/hs20.c
index 1a836666..dd96efaa 100644
--- a/freebsd/contrib/wpa/src/ap/hs20.c
+++ b/freebsd/contrib/wpa/src/ap/hs20.c
@@ -13,9 +13,11 @@
#include "common.h"
#include "common/ieee802_11_defs.h"
+#include "common/wpa_ctrl.h"
#include "hostapd.h"
#include "ap_config.h"
#include "ap_drv_ops.h"
+#include "sta_info.h"
#include "hs20.h"
@@ -25,17 +27,20 @@ u8 * hostapd_eid_hs20_indication(struct hostapd_data *hapd, u8 *eid)
if (!hapd->conf->hs20)
return eid;
*eid++ = WLAN_EID_VENDOR_SPECIFIC;
- *eid++ = 7;
+ *eid++ = hapd->conf->hs20_release < 2 ? 5 : 7;
WPA_PUT_BE24(eid, OUI_WFA);
eid += 3;
*eid++ = HS20_INDICATION_OUI_TYPE;
- conf = HS20_VERSION; /* Release Number */
- conf |= HS20_ANQP_DOMAIN_ID_PRESENT;
+ conf = (hapd->conf->hs20_release - 1) << 4; /* Release Number */
+ if (hapd->conf->hs20_release >= 2)
+ conf |= HS20_ANQP_DOMAIN_ID_PRESENT;
if (hapd->conf->disable_dgaf)
conf |= HS20_DGAF_DISABLED;
*eid++ = conf;
- WPA_PUT_LE16(eid, hapd->conf->anqp_domain_id);
- eid += 2;
+ if (hapd->conf->hs20_release >= 2) {
+ WPA_PUT_LE16(eid, hapd->conf->anqp_domain_id);
+ eid += 2;
+ }
return eid;
}
@@ -84,6 +89,10 @@ u8 * hostapd_eid_osen(struct hostapd_data *hapd, u8 *eid)
capab |= WPA_CAPABILITY_MFPR;
}
#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_OCV
+ if (hapd->conf->ocv)
+ capab |= WPA_CAPABILITY_OCVC;
+#endif /* CONFIG_OCV */
WPA_PUT_LE16(eid, capab);
eid += 2;
@@ -177,3 +186,72 @@ int hs20_send_wnm_notification_deauth_req(struct hostapd_data *hapd,
return ret;
}
+
+
+int hs20_send_wnm_notification_t_c(struct hostapd_data *hapd,
+ const u8 *addr, const char *url)
+{
+ struct wpabuf *buf;
+ int ret;
+ size_t url_len;
+
+ if (!url) {
+ wpa_printf(MSG_INFO, "HS 2.0: No T&C Server URL available");
+ return -1;
+ }
+
+ url_len = os_strlen(url);
+ if (5 + url_len > 255) {
+ wpa_printf(MSG_INFO,
+ "HS 2.0: Too long T&C Server URL for WNM-Notification: '%s'",
+ url);
+ return -1;
+ }
+
+ buf = wpabuf_alloc(4 + 7 + url_len);
+ if (!buf)
+ return -1;
+
+ wpabuf_put_u8(buf, WLAN_ACTION_WNM);
+ wpabuf_put_u8(buf, WNM_NOTIFICATION_REQ);
+ wpabuf_put_u8(buf, 1); /* Dialog token */
+ wpabuf_put_u8(buf, 1); /* Type - 1 reserved for WFA */
+
+ /* Terms and Conditions Acceptance subelement */
+ wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
+ wpabuf_put_u8(buf, 4 + 1 + url_len);
+ wpabuf_put_be24(buf, OUI_WFA);
+ wpabuf_put_u8(buf, HS20_WNM_T_C_ACCEPTANCE);
+ wpabuf_put_u8(buf, url_len);
+ wpabuf_put_str(buf, url);
+
+ ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
+ wpabuf_head(buf), wpabuf_len(buf));
+
+ wpabuf_free(buf);
+
+ return ret;
+}
+
+
+void hs20_t_c_filtering(struct hostapd_data *hapd, struct sta_info *sta,
+ int enabled)
+{
+ if (enabled) {
+ wpa_printf(MSG_DEBUG,
+ "HS 2.0: Terms and Conditions filtering required for "
+ MACSTR, MAC2STR(sta->addr));
+ sta->hs20_t_c_filtering = 1;
+ /* TODO: Enable firewall filtering for the STA */
+ wpa_msg(hapd->msg_ctx, MSG_INFO, HS20_T_C_FILTERING_ADD MACSTR,
+ MAC2STR(sta->addr));
+ } else {
+ wpa_printf(MSG_DEBUG,
+ "HS 2.0: Terms and Conditions filtering not required for "
+ MACSTR, MAC2STR(sta->addr));
+ sta->hs20_t_c_filtering = 0;
+ /* TODO: Disable firewall filtering for the STA */
+ wpa_msg(hapd->msg_ctx, MSG_INFO,
+ HS20_T_C_FILTERING_REMOVE MACSTR, MAC2STR(sta->addr));
+ }
+}
diff --git a/freebsd/contrib/wpa/src/ap/hs20.h b/freebsd/contrib/wpa/src/ap/hs20.h
index 152439f4..e99e26e9 100644
--- a/freebsd/contrib/wpa/src/ap/hs20.h
+++ b/freebsd/contrib/wpa/src/ap/hs20.h
@@ -18,5 +18,9 @@ int hs20_send_wnm_notification(struct hostapd_data *hapd, const u8 *addr,
int hs20_send_wnm_notification_deauth_req(struct hostapd_data *hapd,
const u8 *addr,
const struct wpabuf *payload);
+int hs20_send_wnm_notification_t_c(struct hostapd_data *hapd,
+ const u8 *addr, const char *url);
+void hs20_t_c_filtering(struct hostapd_data *hapd, struct sta_info *sta,
+ int enabled);
#endif /* HS20_H */
diff --git a/freebsd/contrib/wpa/src/ap/ieee802_11.h b/freebsd/contrib/wpa/src/ap/ieee802_11.h
index 0327dec2..db7badcf 100644
--- a/freebsd/contrib/wpa/src/ap/ieee802_11.h
+++ b/freebsd/contrib/wpa/src/ap/ieee802_11.h
@@ -16,6 +16,8 @@ struct hostapd_frame_info;
struct ieee80211_ht_capabilities;
struct ieee80211_vht_capabilities;
struct ieee80211_mgmt;
+struct vlan_description;
+struct hostapd_sta_wpa_psk_short;
int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
struct hostapd_frame_info *fi);
@@ -55,6 +57,9 @@ u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_vendor_vht(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_txpower_envelope(struct hostapd_data *hapd, u8 *eid);
+u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid);
+u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid);
+u8 * hostapd_eid_he_mu_edca_parameter_set(struct hostapd_data *hapd, u8 *eid);
int hostapd_ht_operation_update(struct hostapd_iface *iface);
void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
@@ -76,6 +81,8 @@ void ht40_intolerant_add(struct hostapd_iface *iface, struct sta_info *sta);
void ht40_intolerant_remove(struct hostapd_iface *iface, struct sta_info *sta);
u16 copy_sta_vht_capab(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *vht_capab);
+u16 copy_sta_vht_oper(struct hostapd_data *hapd, struct sta_info *sta,
+ const u8 *vht_oper);
u16 set_sta_vht_opmode(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *vht_opmode);
void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
@@ -87,8 +94,8 @@ void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd,
struct sta_info *sta, u8 *eid);
void ieee802_11_sa_query_action(struct hostapd_data *hapd,
- const u8 *sa, const u8 action_type,
- const u8 *trans_id);
+ const struct ieee80211_mgmt *mgmt,
+ size_t len);
u8 * hostapd_eid_interworking(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_adv_proto(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_roaming_consortium(struct hostapd_data *hapd, u8 *eid);
@@ -116,6 +123,9 @@ u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid, size_t len);
u8 hostapd_mbo_ie_len(struct hostapd_data *hapd);
+u8 * hostapd_eid_mbo_rssi_assoc_rej(struct hostapd_data *hapd, u8 *eid,
+ size_t len, int delta);
+
#else /* CONFIG_MBO */
static inline u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid,
@@ -135,4 +145,36 @@ void ap_copy_sta_supp_op_classes(struct sta_info *sta,
const u8 *supp_op_classes,
size_t supp_op_classes_len);
+u8 * hostapd_eid_fils_indic(struct hostapd_data *hapd, u8 *eid, int hessid);
+void ieee802_11_finish_fils_auth(struct hostapd_data *hapd,
+ struct sta_info *sta, int success,
+ struct wpabuf *erp_resp,
+ const u8 *msk, size_t msk_len);
+u8 * owe_assoc_req_process(struct hostapd_data *hapd, struct sta_info *sta,
+ const u8 *owe_dh, u8 owe_dh_len,
+ u8 *owe_buf, size_t owe_buf_len, u16 *reason);
+void fils_hlp_timeout(void *eloop_ctx, void *eloop_data);
+void fils_hlp_finish_assoc(struct hostapd_data *hapd, struct sta_info *sta);
+void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta,
+ const u8 *pos, size_t len, u16 auth_alg,
+ u16 auth_transaction, u16 status_code,
+ void (*cb)(struct hostapd_data *hapd,
+ struct sta_info *sta,
+ u16 resp, struct wpabuf *data, int pub));
+
+size_t hostapd_eid_owe_trans_len(struct hostapd_data *hapd);
+u8 * hostapd_eid_owe_trans(struct hostapd_data *hapd, u8 *eid, size_t len);
+int ieee802_11_allowed_address(struct hostapd_data *hapd, const u8 *addr,
+ const u8 *msg, size_t len, u32 *session_timeout,
+ u32 *acct_interim_interval,
+ struct vlan_description *vlan_id,
+ struct hostapd_sta_wpa_psk_short **psk,
+ char **identity, char **radius_cui,
+ int is_probe_req);
+
+int get_tx_parameters(struct sta_info *sta, int ap_max_chanwidth,
+ int ap_seg1_idx, int *bandwidth, int *seg1_idx);
+
+void auth_sae_process_commit(void *eloop_ctx, void *user_ctx);
+
#endif /* IEEE802_11_H */
diff --git a/freebsd/contrib/wpa/src/ap/ieee802_11_auth.h b/freebsd/contrib/wpa/src/ap/ieee802_11_auth.h
index 71f53b96..5aece518 100644
--- a/freebsd/contrib/wpa/src/ap/ieee802_11_auth.h
+++ b/freebsd/contrib/wpa/src/ap/ieee802_11_auth.h
@@ -23,7 +23,8 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
u32 *acct_interim_interval,
struct vlan_description *vlan_id,
struct hostapd_sta_wpa_psk_short **psk,
- char **identity, char **radius_cui);
+ char **identity, char **radius_cui,
+ int is_probe_req);
int hostapd_acl_init(struct hostapd_data *hapd);
void hostapd_acl_deinit(struct hostapd_data *hapd);
void hostapd_free_psk_list(struct hostapd_sta_wpa_psk_short *psk);
diff --git a/freebsd/contrib/wpa/src/ap/ieee802_11_shared.c b/freebsd/contrib/wpa/src/ap/ieee802_11_shared.c
index 8a08e93d..2302d486 100644
--- a/freebsd/contrib/wpa/src/ap/ieee802_11_shared.c
+++ b/freebsd/contrib/wpa/src/ap/ieee802_11_shared.c
@@ -12,10 +12,12 @@
#include "utils/common.h"
#include "common/ieee802_11_defs.h"
+#include "common/ocv.h"
#include "hostapd.h"
#include "sta_info.h"
#include "ap_config.h"
#include "ap_drv_ops.h"
+#include "wpa_auth.h"
#include "ieee802_11.h"
@@ -51,7 +53,12 @@ u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd,
void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
const u8 *addr, const u8 *trans_id)
{
- struct ieee80211_mgmt mgmt;
+#ifdef CONFIG_OCV
+ struct sta_info *sta;
+#endif /* CONFIG_OCV */
+ struct ieee80211_mgmt *mgmt;
+ u8 *oci_ie = NULL;
+ u8 oci_ie_len = 0;
u8 *end;
wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Request to "
@@ -59,19 +66,61 @@ void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID",
trans_id, WLAN_SA_QUERY_TR_ID_LEN);
- os_memset(&mgmt, 0, sizeof(mgmt));
- mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
- WLAN_FC_STYPE_ACTION);
- os_memcpy(mgmt.da, addr, ETH_ALEN);
- os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
- os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
- mgmt.u.action.category = WLAN_ACTION_SA_QUERY;
- mgmt.u.action.u.sa_query_req.action = WLAN_SA_QUERY_REQUEST;
- os_memcpy(mgmt.u.action.u.sa_query_req.trans_id, trans_id,
+#ifdef CONFIG_OCV
+ sta = ap_get_sta(hapd, addr);
+ if (sta && wpa_auth_uses_ocv(sta->wpa_sm)) {
+ struct wpa_channel_info ci;
+
+ if (hostapd_drv_channel_info(hapd, &ci) != 0) {
+ wpa_printf(MSG_WARNING,
+ "Failed to get channel info for OCI element in SA Query Request");
+ return;
+ }
+
+ oci_ie_len = OCV_OCI_EXTENDED_LEN;
+ oci_ie = os_zalloc(oci_ie_len);
+ if (!oci_ie) {
+ wpa_printf(MSG_WARNING,
+ "Failed to allocate buffer for OCI element in SA Query Request");
+ return;
+ }
+
+ if (ocv_insert_extended_oci(&ci, oci_ie) < 0) {
+ os_free(oci_ie);
+ return;
+ }
+ }
+#endif /* CONFIG_OCV */
+
+ mgmt = os_zalloc(sizeof(*mgmt) + oci_ie_len);
+ if (!mgmt) {
+ wpa_printf(MSG_DEBUG,
+ "Failed to allocate buffer for SA Query Response frame");
+ os_free(oci_ie);
+ return;
+ }
+
+ mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
+ WLAN_FC_STYPE_ACTION);
+ os_memcpy(mgmt->da, addr, ETH_ALEN);
+ os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
+ os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
+ mgmt->u.action.category = WLAN_ACTION_SA_QUERY;
+ mgmt->u.action.u.sa_query_req.action = WLAN_SA_QUERY_REQUEST;
+ os_memcpy(mgmt->u.action.u.sa_query_req.trans_id, trans_id,
WLAN_SA_QUERY_TR_ID_LEN);
- end = mgmt.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN;
- if (hostapd_drv_send_mlme(hapd, &mgmt, end - (u8 *) &mgmt, 0) < 0)
+ end = mgmt->u.action.u.sa_query_req.variable;
+#ifdef CONFIG_OCV
+ if (oci_ie_len > 0) {
+ os_memcpy(end, oci_ie, oci_ie_len);
+ end += oci_ie_len;
+ }
+#endif /* CONFIG_OCV */
+ if (hostapd_drv_send_mlme(hapd, mgmt, end - (u8 *) mgmt, 0) < 0)
wpa_printf(MSG_INFO, "ieee802_11_send_sa_query_req: send failed");
+
+ os_free(mgmt);
+ os_free(oci_ie);
}
@@ -79,7 +128,9 @@ static void ieee802_11_send_sa_query_resp(struct hostapd_data *hapd,
const u8 *sa, const u8 *trans_id)
{
struct sta_info *sta;
- struct ieee80211_mgmt resp;
+ struct ieee80211_mgmt *resp;
+ u8 *oci_ie = NULL;
+ u8 oci_ie_len = 0;
u8 *end;
wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Request from "
@@ -94,30 +145,123 @@ static void ieee802_11_send_sa_query_resp(struct hostapd_data *hapd,
return;
}
+#ifdef CONFIG_OCV
+ if (wpa_auth_uses_ocv(sta->wpa_sm)) {
+ struct wpa_channel_info ci;
+
+ if (hostapd_drv_channel_info(hapd, &ci) != 0) {
+ wpa_printf(MSG_WARNING,
+ "Failed to get channel info for OCI element in SA Query Response");
+ return;
+ }
+
+ oci_ie_len = OCV_OCI_EXTENDED_LEN;
+ oci_ie = os_zalloc(oci_ie_len);
+ if (!oci_ie) {
+ wpa_printf(MSG_WARNING,
+ "Failed to allocate buffer for for OCI element in SA Query Response");
+ return;
+ }
+
+ if (ocv_insert_extended_oci(&ci, oci_ie) < 0) {
+ os_free(oci_ie);
+ return;
+ }
+ }
+#endif /* CONFIG_OCV */
+
+ resp = os_zalloc(sizeof(*resp) + oci_ie_len);
+ if (!resp) {
+ wpa_printf(MSG_DEBUG,
+ "Failed to allocate buffer for SA Query Response frame");
+ os_free(oci_ie);
+ return;
+ }
+
wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Response to "
MACSTR, MAC2STR(sa));
- os_memset(&resp, 0, sizeof(resp));
- resp.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
- WLAN_FC_STYPE_ACTION);
- os_memcpy(resp.da, sa, ETH_ALEN);
- os_memcpy(resp.sa, hapd->own_addr, ETH_ALEN);
- os_memcpy(resp.bssid, hapd->own_addr, ETH_ALEN);
- resp.u.action.category = WLAN_ACTION_SA_QUERY;
- resp.u.action.u.sa_query_req.action = WLAN_SA_QUERY_RESPONSE;
- os_memcpy(resp.u.action.u.sa_query_req.trans_id, trans_id,
+ resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
+ WLAN_FC_STYPE_ACTION);
+ os_memcpy(resp->da, sa, ETH_ALEN);
+ os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
+ os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
+ resp->u.action.category = WLAN_ACTION_SA_QUERY;
+ resp->u.action.u.sa_query_req.action = WLAN_SA_QUERY_RESPONSE;
+ os_memcpy(resp->u.action.u.sa_query_req.trans_id, trans_id,
WLAN_SA_QUERY_TR_ID_LEN);
- end = resp.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN;
- if (hostapd_drv_send_mlme(hapd, &resp, end - (u8 *) &resp, 0) < 0)
+ end = resp->u.action.u.sa_query_req.variable;
+#ifdef CONFIG_OCV
+ if (oci_ie_len > 0) {
+ os_memcpy(end, oci_ie, oci_ie_len);
+ end += oci_ie_len;
+ }
+#endif /* CONFIG_OCV */
+ if (hostapd_drv_send_mlme(hapd, resp, end - (u8 *) resp, 0) < 0)
wpa_printf(MSG_INFO, "ieee80211_mgmt_sa_query_request: send failed");
+
+ os_free(resp);
+ os_free(oci_ie);
}
-void ieee802_11_sa_query_action(struct hostapd_data *hapd, const u8 *sa,
- const u8 action_type, const u8 *trans_id)
+void ieee802_11_sa_query_action(struct hostapd_data *hapd,
+ const struct ieee80211_mgmt *mgmt,
+ size_t len)
{
struct sta_info *sta;
int i;
+ const u8 *sa = mgmt->sa;
+ const u8 action_type = mgmt->u.action.u.sa_query_resp.action;
+ const u8 *trans_id = mgmt->u.action.u.sa_query_resp.trans_id;
+
+ if (((const u8 *) mgmt) + len <
+ mgmt->u.action.u.sa_query_resp.variable) {
+ wpa_printf(MSG_DEBUG,
+ "IEEE 802.11: Too short SA Query Action frame (len=%lu)",
+ (unsigned long) len);
+ return;
+ }
+
+ sta = ap_get_sta(hapd, sa);
+
+#ifdef CONFIG_OCV
+ if (sta && wpa_auth_uses_ocv(sta->wpa_sm)) {
+ struct ieee802_11_elems elems;
+ struct wpa_channel_info ci;
+ int tx_chanwidth;
+ int tx_seg1_idx;
+ size_t ies_len;
+ const u8 *ies;
+
+ ies = mgmt->u.action.u.sa_query_resp.variable;
+ ies_len = len - (ies - (u8 *) mgmt);
+ if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) ==
+ ParseFailed) {
+ wpa_printf(MSG_DEBUG,
+ "SA Query: Failed to parse elements");
+ return;
+ }
+
+ if (hostapd_drv_channel_info(hapd, &ci) != 0) {
+ wpa_printf(MSG_WARNING,
+ "Failed to get channel info to validate received OCI in SA Query Action frame");
+ return;
+ }
+
+ if (get_sta_tx_parameters(sta->wpa_sm,
+ channel_width_to_int(ci.chanwidth),
+ ci.seg1_idx, &tx_chanwidth,
+ &tx_seg1_idx) < 0)
+ return;
+
+ if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci,
+ tx_chanwidth, tx_seg1_idx) != 0) {
+ wpa_printf(MSG_WARNING, "%s", ocv_errorstr);
+ return;
+ }
+ }
+#endif /* CONFIG_OCV */
if (action_type == WLAN_SA_QUERY_REQUEST) {
ieee802_11_send_sa_query_resp(hapd, sa, trans_id);
@@ -137,7 +281,6 @@ void ieee802_11_sa_query_action(struct hostapd_data *hapd, const u8 *sa,
/* MLME-SAQuery.confirm */
- sta = ap_get_sta(hapd, sa);
if (sta == NULL || sta->sa_query_trans_id == NULL) {
wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching STA with "
"pending SA Query request found");
@@ -180,6 +323,10 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
case 1: /* Bits 8-15 */
if (hapd->conf->proxy_arp)
*pos |= 0x10; /* Bit 12 - Proxy ARP */
+ if (hapd->conf->coloc_intf_reporting) {
+ /* Bit 13 - Collocated Interference Reporting */
+ *pos |= 0x20;
+ }
break;
case 2: /* Bits 16-23 */
if (hapd->conf->wnm_sleep_mode)
@@ -188,9 +335,9 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
*pos |= 0x08; /* Bit 19 - BSS Transition */
break;
case 3: /* Bits 24-31 */
-#ifdef CONFIG_WNM
+#ifdef CONFIG_WNM_AP
*pos |= 0x02; /* Bit 25 - SSID List */
-#endif /* CONFIG_WNM */
+#endif /* CONFIG_WNM_AP */
if (hapd->conf->time_advertisement == 2)
*pos |= 0x08; /* Bit 27 - UTC TSF Offset */
if (hapd->conf->interworking)
@@ -220,12 +367,36 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
if (hapd->conf->ssid.utf8_ssid)
*pos |= 0x01; /* Bit 48 - UTF-8 SSID */
break;
+ case 7: /* Bits 56-63 */
+ break;
case 8: /* Bits 64-71 */
if (hapd->conf->ftm_responder)
*pos |= 0x40; /* Bit 70 - FTM responder */
if (hapd->conf->ftm_initiator)
*pos |= 0x80; /* Bit 71 - FTM initiator */
break;
+ case 9: /* Bits 72-79 */
+#ifdef CONFIG_FILS
+ if ((hapd->conf->wpa & WPA_PROTO_RSN) &&
+ wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt))
+ *pos |= 0x01;
+#endif /* CONFIG_FILS */
+ break;
+ case 10: /* Bits 80-87 */
+#ifdef CONFIG_SAE
+ if (hapd->conf->wpa &&
+ wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt)) {
+ int in_use = hostapd_sae_pw_id_in_use(hapd->conf);
+
+ if (in_use)
+ *pos |= 0x02; /* Bit 81 - SAE Password
+ * Identifiers In Use */
+ if (in_use == 2)
+ *pos |= 0x04; /* Bit 82 - SAE Password
+ * Identifiers Used Exclusively */
+ }
+#endif /* CONFIG_SAE */
+ break;
}
}
@@ -248,10 +419,10 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
if (len < 9 &&
(hapd->conf->ftm_initiator || hapd->conf->ftm_responder))
len = 9;
-#ifdef CONFIG_WNM
+#ifdef CONFIG_WNM_AP
if (len < 4)
len = 4;
-#endif /* CONFIG_WNM */
+#endif /* CONFIG_WNM_AP */
#ifdef CONFIG_HS20
if (hapd->conf->hs20 && len < 6)
len = 6;
@@ -260,6 +431,17 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
if (hapd->conf->mbo_enabled && len < 6)
len = 6;
#endif /* CONFIG_MBO */
+#ifdef CONFIG_FILS
+ if ((!(hapd->conf->wpa & WPA_PROTO_RSN) ||
+ !wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt)) && len < 10)
+ len = 10;
+#endif /* CONFIG_FILS */
+#ifdef CONFIG_SAE
+ if (len < 11 && hapd->conf->wpa &&
+ wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
+ hostapd_sae_pw_id_in_use(hapd->conf))
+ len = 11;
+#endif /* CONFIG_SAE */
if (len < hapd->iface->extended_capa_len)
len = hapd->iface->extended_capa_len;
if (len == 0)
@@ -434,7 +616,7 @@ u8 * hostapd_eid_time_zone(struct hostapd_data *hapd, u8 *eid)
{
size_t len;
- if (hapd->conf->time_advertisement != 2)
+ if (hapd->conf->time_advertisement != 2 || !hapd->conf->time_zone)
return eid;
len = os_strlen(hapd->conf->time_zone);
@@ -505,7 +687,7 @@ u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid)
{
u8 *pos = eid;
-#ifdef CONFIG_WNM
+#ifdef CONFIG_WNM_AP
if (hapd->conf->ap_max_inactivity > 0) {
unsigned int val;
*pos++ = WLAN_EID_BSS_MAX_IDLE_PERIOD;
@@ -523,7 +705,7 @@ u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid)
pos += 2;
*pos++ = 0x00; /* TODO: Protected Keep-Alive Required */
}
-#endif /* CONFIG_WNM */
+#endif /* CONFIG_WNM_AP */
return pos;
}
@@ -531,25 +713,56 @@ u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid)
#ifdef CONFIG_MBO
+u8 * hostapd_eid_mbo_rssi_assoc_rej(struct hostapd_data *hapd, u8 *eid,
+ size_t len, int delta)
+{
+ u8 mbo[4];
+
+ mbo[0] = OCE_ATTR_ID_RSSI_BASED_ASSOC_REJECT;
+ mbo[1] = 2;
+ /* Delta RSSI */
+ mbo[2] = delta;
+ /* Retry delay */
+ mbo[3] = hapd->iconf->rssi_reject_assoc_timeout;
+
+ return eid + mbo_add_ie(eid, len, mbo, 4);
+}
+
+
u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid, size_t len)
{
- u8 mbo[6], *mbo_pos = mbo;
+ u8 mbo[9], *mbo_pos = mbo;
u8 *pos = eid;
- if (!hapd->conf->mbo_enabled)
+ if (!hapd->conf->mbo_enabled &&
+ !OCE_STA_CFON_ENABLED(hapd) && !OCE_AP_ENABLED(hapd))
return eid;
- *mbo_pos++ = MBO_ATTR_ID_AP_CAPA_IND;
- *mbo_pos++ = 1;
- /* Not Cellular aware */
- *mbo_pos++ = 0;
+ if (hapd->conf->mbo_enabled) {
+ *mbo_pos++ = MBO_ATTR_ID_AP_CAPA_IND;
+ *mbo_pos++ = 1;
+ /* Not Cellular aware */
+ *mbo_pos++ = 0;
+ }
- if (hapd->mbo_assoc_disallow) {
+ if (hapd->conf->mbo_enabled && hapd->mbo_assoc_disallow) {
*mbo_pos++ = MBO_ATTR_ID_ASSOC_DISALLOW;
*mbo_pos++ = 1;
*mbo_pos++ = hapd->mbo_assoc_disallow;
}
+ if (OCE_STA_CFON_ENABLED(hapd) || OCE_AP_ENABLED(hapd)) {
+ u8 ctrl;
+
+ ctrl = OCE_RELEASE;
+ if (OCE_STA_CFON_ENABLED(hapd) && !OCE_AP_ENABLED(hapd))
+ ctrl |= OCE_IS_STA_CFON;
+
+ *mbo_pos++ = OCE_ATTR_ID_CAPA_IND;
+ *mbo_pos++ = 1;
+ *mbo_pos++ = ctrl;
+ }
+
pos += mbo_add_ie(pos, len, mbo, mbo_pos - mbo);
return pos;
@@ -558,19 +771,91 @@ u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid, size_t len)
u8 hostapd_mbo_ie_len(struct hostapd_data *hapd)
{
- if (!hapd->conf->mbo_enabled)
+ u8 len;
+
+ if (!hapd->conf->mbo_enabled &&
+ !OCE_STA_CFON_ENABLED(hapd) && !OCE_AP_ENABLED(hapd))
return 0;
/*
* MBO IE header (6) + Capability Indication attribute (3) +
* Association Disallowed attribute (3) = 12
*/
- return 6 + 3 + (hapd->mbo_assoc_disallow ? 3 : 0);
+ len = 6;
+ if (hapd->conf->mbo_enabled)
+ len += 3 + (hapd->mbo_assoc_disallow ? 3 : 0);
+
+ /* OCE capability indication attribute (3) */
+ if (OCE_STA_CFON_ENABLED(hapd) || OCE_AP_ENABLED(hapd))
+ len += 3;
+
+ return len;
}
#endif /* CONFIG_MBO */
+#ifdef CONFIG_OWE
+static int hostapd_eid_owe_trans_enabled(struct hostapd_data *hapd)
+{
+ return hapd->conf->owe_transition_ssid_len > 0 &&
+ !is_zero_ether_addr(hapd->conf->owe_transition_bssid);
+}
+#endif /* CONFIG_OWE */
+
+
+size_t hostapd_eid_owe_trans_len(struct hostapd_data *hapd)
+{
+#ifdef CONFIG_OWE
+ if (!hostapd_eid_owe_trans_enabled(hapd))
+ return 0;
+ return 6 + ETH_ALEN + 1 + hapd->conf->owe_transition_ssid_len;
+#else /* CONFIG_OWE */
+ return 0;
+#endif /* CONFIG_OWE */
+}
+
+
+u8 * hostapd_eid_owe_trans(struct hostapd_data *hapd, u8 *eid,
+ size_t len)
+{
+#ifdef CONFIG_OWE
+ u8 *pos = eid;
+ size_t elen;
+
+ if (hapd->conf->owe_transition_ifname[0] &&
+ !hostapd_eid_owe_trans_enabled(hapd))
+ hostapd_owe_trans_get_info(hapd);
+
+ if (!hostapd_eid_owe_trans_enabled(hapd))
+ return pos;
+
+ elen = hostapd_eid_owe_trans_len(hapd);
+ if (len < elen) {
+ wpa_printf(MSG_DEBUG,
+ "OWE: Not enough room in the buffer for OWE IE");
+ return pos;
+ }
+
+ *pos++ = WLAN_EID_VENDOR_SPECIFIC;
+ *pos++ = elen - 2;
+ WPA_PUT_BE24(pos, OUI_WFA);
+ pos += 3;
+ *pos++ = OWE_OUI_TYPE;
+ os_memcpy(pos, hapd->conf->owe_transition_bssid, ETH_ALEN);
+ pos += ETH_ALEN;
+ *pos++ = hapd->conf->owe_transition_ssid_len;
+ os_memcpy(pos, hapd->conf->owe_transition_ssid,
+ hapd->conf->owe_transition_ssid_len);
+ pos += hapd->conf->owe_transition_ssid_len;
+
+ return pos;
+#else /* CONFIG_OWE */
+ return eid;
+#endif /* CONFIG_OWE */
+}
+
+
void ap_copy_sta_supp_op_classes(struct sta_info *sta,
const u8 *supp_op_classes,
size_t supp_op_classes_len)
@@ -586,3 +871,134 @@ void ap_copy_sta_supp_op_classes(struct sta_info *sta,
os_memcpy(sta->supp_op_classes + 1, supp_op_classes,
supp_op_classes_len);
}
+
+
+u8 * hostapd_eid_fils_indic(struct hostapd_data *hapd, u8 *eid, int hessid)
+{
+ u8 *pos = eid;
+#ifdef CONFIG_FILS
+ u8 *len;
+ u16 fils_info = 0;
+ size_t realms;
+ struct fils_realm *realm;
+
+ if (!(hapd->conf->wpa & WPA_PROTO_RSN) ||
+ !wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt))
+ return pos;
+
+ realms = dl_list_len(&hapd->conf->fils_realms);
+ if (realms > 7)
+ realms = 7; /* 3 bit count field limits this to max 7 */
+
+ *pos++ = WLAN_EID_FILS_INDICATION;
+ len = pos++;
+ /* TODO: B0..B2: Number of Public Key Identifiers */
+ if (hapd->conf->erp_domain) {
+ /* B3..B5: Number of Realm Identifiers */
+ fils_info |= realms << 3;
+ }
+ /* TODO: B6: FILS IP Address Configuration */
+ if (hapd->conf->fils_cache_id_set)
+ fils_info |= BIT(7);
+ if (hessid && !is_zero_ether_addr(hapd->conf->hessid))
+ fils_info |= BIT(8); /* HESSID Included */
+ /* FILS Shared Key Authentication without PFS Supported */
+ fils_info |= BIT(9);
+ if (hapd->conf->fils_dh_group) {
+ /* FILS Shared Key Authentication with PFS Supported */
+ fils_info |= BIT(10);
+ }
+ /* TODO: B11: FILS Public Key Authentication Supported */
+ /* B12..B15: Reserved */
+ WPA_PUT_LE16(pos, fils_info);
+ pos += 2;
+ if (hapd->conf->fils_cache_id_set) {
+ os_memcpy(pos, hapd->conf->fils_cache_id, FILS_CACHE_ID_LEN);
+ pos += FILS_CACHE_ID_LEN;
+ }
+ if (hessid && !is_zero_ether_addr(hapd->conf->hessid)) {
+ os_memcpy(pos, hapd->conf->hessid, ETH_ALEN);
+ pos += ETH_ALEN;
+ }
+
+ dl_list_for_each(realm, &hapd->conf->fils_realms, struct fils_realm,
+ list) {
+ if (realms == 0)
+ break;
+ realms--;
+ os_memcpy(pos, realm->hash, 2);
+ pos += 2;
+ }
+ *len = pos - len - 1;
+#endif /* CONFIG_FILS */
+
+ return pos;
+}
+
+
+#ifdef CONFIG_OCV
+int get_tx_parameters(struct sta_info *sta, int ap_max_chanwidth,
+ int ap_seg1_idx, int *bandwidth, int *seg1_idx)
+{
+ int ht_40mhz = 0;
+ int vht_80p80 = 0;
+ int requested_bw;
+
+ if (sta->ht_capabilities)
+ ht_40mhz = !!(sta->ht_capabilities->ht_capabilities_info &
+ HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET);
+
+ if (sta->vht_operation) {
+ struct ieee80211_vht_operation *oper = sta->vht_operation;
+
+ /*
+ * If a VHT Operation element was present, use it to determine
+ * the supported channel bandwidth.
+ */
+ if (oper->vht_op_info_chwidth == 0) {
+ requested_bw = ht_40mhz ? 40 : 20;
+ } else if (oper->vht_op_info_chan_center_freq_seg1_idx == 0) {
+ requested_bw = 80;
+ } else {
+ int diff;
+
+ requested_bw = 160;
+ diff = abs((int)
+ oper->vht_op_info_chan_center_freq_seg0_idx -
+ (int)
+ oper->vht_op_info_chan_center_freq_seg1_idx);
+ vht_80p80 = oper->vht_op_info_chan_center_freq_seg1_idx
+ != 0 && diff > 16;
+ }
+ } else if (sta->vht_capabilities) {
+ struct ieee80211_vht_capabilities *capab;
+ int vht_chanwidth;
+
+ capab = sta->vht_capabilities;
+
+ /*
+ * If only the VHT Capabilities element is present (e.g., for
+ * normal clients), use it to determine the supported channel
+ * bandwidth.
+ */
+ vht_chanwidth = capab->vht_capabilities_info &
+ VHT_CAP_SUPP_CHAN_WIDTH_MASK;
+ vht_80p80 = capab->vht_capabilities_info &
+ VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
+
+ /* TODO: Also take into account Extended NSS BW Support field */
+ requested_bw = vht_chanwidth ? 160 : 80;
+ } else {
+ requested_bw = ht_40mhz ? 40 : 20;
+ }
+
+ *bandwidth = requested_bw < ap_max_chanwidth ?
+ requested_bw : ap_max_chanwidth;
+
+ *seg1_idx = 0;
+ if (ap_seg1_idx && vht_80p80)
+ *seg1_idx = ap_seg1_idx;
+
+ return 0;
+}
+#endif /* CONFIG_OCV */
diff --git a/freebsd/contrib/wpa/src/ap/pmksa_cache_auth.h b/freebsd/contrib/wpa/src/ap/pmksa_cache_auth.h
index d8d9c5a2..2ef21743 100644
--- a/freebsd/contrib/wpa/src/ap/pmksa_cache_auth.h
+++ b/freebsd/contrib/wpa/src/ap/pmksa_cache_auth.h
@@ -35,6 +35,7 @@ struct rsn_pmksa_cache_entry {
};
struct rsn_pmksa_cache;
+struct radius_das_attrs;
struct rsn_pmksa_cache *
pmksa_cache_auth_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry,
@@ -53,6 +54,13 @@ pmksa_cache_auth_add(struct rsn_pmksa_cache *pmksa,
const u8 *aa, const u8 *spa, int session_timeout,
struct eapol_state_machine *eapol, int akmp);
struct rsn_pmksa_cache_entry *
+pmksa_cache_auth_create_entry(const u8 *pmk, size_t pmk_len, const u8 *pmkid,
+ const u8 *kck, size_t kck_len, const u8 *aa,
+ const u8 *spa, int session_timeout,
+ struct eapol_state_machine *eapol, int akmp);
+int pmksa_cache_auth_add_entry(struct rsn_pmksa_cache *pmksa,
+ struct rsn_pmksa_cache_entry *entry);
+struct rsn_pmksa_cache_entry *
pmksa_cache_add_okc(struct rsn_pmksa_cache *pmksa,
const struct rsn_pmksa_cache_entry *old_entry,
const u8 *aa, const u8 *pmkid);
@@ -65,5 +73,7 @@ int pmksa_cache_auth_radius_das_disconnect(struct rsn_pmksa_cache *pmksa,
struct radius_das_attrs *attr);
int pmksa_cache_auth_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len);
void pmksa_cache_auth_flush(struct rsn_pmksa_cache *pmksa);
+int pmksa_cache_auth_list_mesh(struct rsn_pmksa_cache *pmksa, const u8 *addr,
+ char *buf, size_t len);
#endif /* PMKSA_CACHE_H */
diff --git a/freebsd/contrib/wpa/src/ap/sta_info.h b/freebsd/contrib/wpa/src/ap/sta_info.h
index 099de62d..ece0c60a 100644
--- a/freebsd/contrib/wpa/src/ap/sta_info.h
+++ b/freebsd/contrib/wpa/src/ap/sta_info.h
@@ -1,6 +1,6 @@
/*
* hostapd / Station table
- * Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2017, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -9,14 +9,11 @@
#ifndef STA_INFO_H
#define STA_INFO_H
-#ifdef CONFIG_MESH
-/* needed for mesh_plink_state enum */
#include "common/defs.h"
-#include "common/wpa_common.h"
-#endif /* CONFIG_MESH */
-
#include "list.h"
#include "vlan.h"
+#include "common/wpa_common.h"
+#include "common/ieee802_11_defs.h"
/* STA flags */
#define WLAN_STA_AUTH BIT(0)
@@ -38,6 +35,8 @@
#define WLAN_STA_WNM_SLEEP_MODE BIT(19)
#define WLAN_STA_VHT_OPMODE_ENABLED BIT(20)
#define WLAN_STA_VENDOR_VHT BIT(21)
+#define WLAN_STA_PENDING_FILS_ERP BIT(22)
+#define WLAN_STA_MULTI_AP BIT(23)
#define WLAN_STA_PENDING_DISASSOC_CB BIT(29)
#define WLAN_STA_PENDING_DEAUTH_CB BIT(30)
#define WLAN_STA_NONERP BIT(31)
@@ -46,6 +45,7 @@
* Supported Rates IEs). */
#define WLAN_SUPP_RATES_MAX 32
+struct hostapd_data;
struct mbo_non_pref_chan_info {
struct mbo_non_pref_chan_info *next;
@@ -68,6 +68,7 @@ struct sta_info {
be32 ipaddr;
struct dl_list ip6addr; /* list head for struct ip6addr */
u16 aid; /* STA's unique AID (1 .. 2007) or 0 if not yet assigned */
+ u16 disconnect_reason_code; /* RADIUS server override */
u32 flags; /* Bitfield of WLAN_STA_* */
u16 capability;
u16 listen_interval; /* or beacon_int for APs */
@@ -113,6 +114,11 @@ struct sta_info {
unsigned int radius_das_match:1;
unsigned int ecsa_supported:1;
unsigned int added_unassoc:1;
+ unsigned int pending_wds_enable:1;
+ unsigned int power_capab:1;
+ unsigned int agreed_to_steer:1;
+ unsigned int hs20_t_c_filtering:1;
+ unsigned int ft_over_ds:1;
u16 auth_alg;
@@ -158,6 +164,7 @@ struct sta_info {
struct ieee80211_ht_capabilities *ht_capabilities;
struct ieee80211_vht_capabilities *vht_capabilities;
+ struct ieee80211_vht_operation *vht_operation;
u8 vht_opmode;
#ifdef CONFIG_IEEE80211W
@@ -170,17 +177,20 @@ struct sta_info {
struct os_reltime sa_query_start;
#endif /* CONFIG_IEEE80211W */
-#ifdef CONFIG_INTERWORKING
+#if defined(CONFIG_INTERWORKING) || defined(CONFIG_DPP)
#define GAS_DIALOG_MAX 8 /* Max concurrent dialog number */
struct gas_dialog_info *gas_dialog;
u8 gas_dialog_next;
-#endif /* CONFIG_INTERWORKING */
+#endif /* CONFIG_INTERWORKING || CONFIG_DPP */
struct wpabuf *wps_ie; /* WPS IE from (Re)Association Request */
struct wpabuf *p2p_ie; /* P2P IE from (Re)Association Request */
struct wpabuf *hs20_ie; /* HS 2.0 IE from (Re)Association Request */
+ /* Hotspot 2.0 Roaming Consortium from (Re)Association Request */
+ struct wpabuf *roaming_consortium;
u8 remediation_method;
char *remediation_url; /* HS 2.0 Subscription Remediation Server URL */
+ char *t_c_url; /* HS 2.0 Terms and Conditions Server URL */
struct wpabuf *hs20_deauth_req;
char *hs20_session_info_url;
int hs20_disassoc_timer;
@@ -195,7 +205,8 @@ struct sta_info {
unsigned int mesh_sae_pmksa_caching:1;
#endif /* CONFIG_SAE */
- u32 session_timeout; /* valid only if session_timeout_set == 1 */
+ /* valid only if session_timeout_set == 1 */
+ struct os_reltime session_timeout;
/* Last Authentication/(Re)Association Request/Action frame sequence
* control */
@@ -207,6 +218,7 @@ struct sta_info {
u8 cell_capa; /* 0 = unknown (not an MBO STA); otherwise,
* enum mbo_cellular_capa values */
struct mbo_non_pref_chan_info *non_pref_chan;
+ int auth_rssi; /* Last Authentication frame RSSI */
#endif /* CONFIG_MBO */
u8 *supp_op_classes; /* Supported Operating Classes element, if
@@ -214,10 +226,55 @@ struct sta_info {
u8 rrm_enabled_capa[5];
+ s8 min_tx_power;
+ s8 max_tx_power;
+
#ifdef CONFIG_TAXONOMY
struct wpabuf *probe_ie_taxonomy;
struct wpabuf *assoc_ie_taxonomy;
#endif /* CONFIG_TAXONOMY */
+
+#ifdef CONFIG_FILS
+ u8 fils_snonce[FILS_NONCE_LEN];
+ u8 fils_session[FILS_SESSION_LEN];
+ u8 fils_erp_pmkid[PMKID_LEN];
+ u8 *fils_pending_assoc_req;
+ size_t fils_pending_assoc_req_len;
+ unsigned int fils_pending_assoc_is_reassoc:1;
+ unsigned int fils_dhcp_rapid_commit_proxy:1;
+ unsigned int fils_erp_pmkid_set:1;
+ unsigned int fils_drv_assoc_finish:1;
+ struct wpabuf *fils_hlp_resp;
+ struct wpabuf *hlp_dhcp_discover;
+ void (*fils_pending_cb)(struct hostapd_data *hapd, struct sta_info *sta,
+ u16 resp, struct wpabuf *data, int pub);
+#ifdef CONFIG_FILS_SK_PFS
+ struct crypto_ecdh *fils_ecdh;
+#endif /* CONFIG_FILS_SK_PFS */
+ struct wpabuf *fils_dh_ss;
+ struct wpabuf *fils_g_sta;
+#endif /* CONFIG_FILS */
+
+#ifdef CONFIG_OWE
+ u8 *owe_pmk;
+ size_t owe_pmk_len;
+ struct crypto_ecdh *owe_ecdh;
+ u16 owe_group;
+#endif /* CONFIG_OWE */
+
+ u8 *ext_capability;
+ char *ifname_wds; /* WDS ifname, if in use */
+
+#ifdef CONFIG_DPP2
+ struct dpp_pfs *dpp_pfs;
+#endif /* CONFIG_DPP2 */
+
+#ifdef CONFIG_TESTING_OPTIONS
+ enum wpa_alg last_tk_alg;
+ int last_tk_key_idx;
+ u8 last_tk[WPA_TK_MAX_LEN];
+ size_t last_tk_len;
+#endif /* CONFIG_TESTING_OPTIONS */
};
@@ -237,8 +294,6 @@ struct sta_info {
#define AP_MAX_INACTIVITY_AFTER_DEAUTH (1 * 5)
-struct hostapd_data;
-
int ap_for_each_sta(struct hostapd_data *hapd,
int (*cb)(struct hostapd_data *hapd, struct sta_info *sta,
void *ctx),
@@ -273,6 +328,8 @@ int ap_sta_set_vlan(struct hostapd_data *hapd, struct sta_info *sta,
void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta);
void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta);
int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta);
+const char * ap_sta_wpa_get_keyid(struct hostapd_data *hapd,
+ struct sta_info *sta);
void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *addr, u16 reason);
@@ -289,5 +346,9 @@ void ap_sta_clear_disconnect_timeouts(struct hostapd_data *hapd,
struct sta_info *sta);
int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen);
+void ap_sta_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
+ struct sta_info *sta);
+int ap_sta_pending_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
+ struct sta_info *sta);
#endif /* STA_INFO_H */
diff --git a/freebsd/contrib/wpa/src/ap/wpa_auth.c b/freebsd/contrib/wpa/src/ap/wpa_auth.c
index 5e0b0bf8..5a1b250c 100644
--- a/freebsd/contrib/wpa/src/ap/wpa_auth.c
+++ b/freebsd/contrib/wpa/src/ap/wpa_auth.c
@@ -2,7 +2,7 @@
/*
* IEEE 802.11 RSN / WPA Authenticator
- * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -15,12 +15,17 @@
#include "utils/state_machine.h"
#include "utils/bitfield.h"
#include "common/ieee802_11_defs.h"
+#include "common/ocv.h"
+#include "crypto/aes.h"
#include "crypto/aes_wrap.h"
+#include "crypto/aes_siv.h"
#include "crypto/crypto.h"
#include "crypto/sha1.h"
#include "crypto/sha256.h"
+#include "crypto/sha384.h"
#include "crypto/random.h"
#include "eapol_auth/eapol_auth_sm.h"
+#include "drivers/driver.h"
#include "ap_config.h"
#include "ieee802_11.h"
#include "wpa_auth.h"
@@ -35,8 +40,14 @@
static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx);
static int wpa_sm_step(struct wpa_state_machine *sm);
-static int wpa_verify_key_mic(int akmp, struct wpa_ptk *PTK, u8 *data,
- size_t data_len);
+static int wpa_verify_key_mic(int akmp, size_t pmk_len, struct wpa_ptk *PTK,
+ u8 *data, size_t data_len);
+#ifdef CONFIG_FILS
+static int wpa_aead_decrypt(struct wpa_state_machine *sm, struct wpa_ptk *ptk,
+ u8 *buf, size_t buf_len, u16 *_key_data_len);
+static struct wpabuf * fils_prepare_plainbuf(struct wpa_state_machine *sm,
+ const struct wpabuf *hlp);
+#endif /* CONFIG_FILS */
static void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx);
static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth,
struct wpa_group *group);
@@ -54,12 +65,12 @@ static void wpa_group_get(struct wpa_authenticator *wpa_auth,
struct wpa_group *group);
static void wpa_group_put(struct wpa_authenticator *wpa_auth,
struct wpa_group *group);
+static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos);
-static const u32 dot11RSNAConfigGroupUpdateCount = 4;
-static const u32 dot11RSNAConfigPairwiseUpdateCount = 4;
static const u32 eapol_key_timeout_first = 100; /* ms */
static const u32 eapol_key_timeout_subseq = 1000; /* ms */
static const u32 eapol_key_timeout_first_group = 500; /* ms */
+static const u32 eapol_key_timeout_no_retrans = 4000; /* ms */
/* TODO: make these configurable */
static const int dot11RSNAConfigPMKLifetime = 43200;
@@ -70,8 +81,8 @@ static const int dot11RSNAConfigSATimeout = 60;
static inline int wpa_auth_mic_failure_report(
struct wpa_authenticator *wpa_auth, const u8 *addr)
{
- if (wpa_auth->cb.mic_failure_report)
- return wpa_auth->cb.mic_failure_report(wpa_auth->cb.ctx, addr);
+ if (wpa_auth->cb->mic_failure_report)
+ return wpa_auth->cb->mic_failure_report(wpa_auth->cb_ctx, addr);
return 0;
}
@@ -79,8 +90,8 @@ static inline int wpa_auth_mic_failure_report(
static inline void wpa_auth_psk_failure_report(
struct wpa_authenticator *wpa_auth, const u8 *addr)
{
- if (wpa_auth->cb.psk_failure_report)
- wpa_auth->cb.psk_failure_report(wpa_auth->cb.ctx, addr);
+ if (wpa_auth->cb->psk_failure_report)
+ wpa_auth->cb->psk_failure_report(wpa_auth->cb_ctx, addr);
}
@@ -88,38 +99,39 @@ static inline void wpa_auth_set_eapol(struct wpa_authenticator *wpa_auth,
const u8 *addr, wpa_eapol_variable var,
int value)
{
- if (wpa_auth->cb.set_eapol)
- wpa_auth->cb.set_eapol(wpa_auth->cb.ctx, addr, var, value);
+ if (wpa_auth->cb->set_eapol)
+ wpa_auth->cb->set_eapol(wpa_auth->cb_ctx, addr, var, value);
}
static inline int wpa_auth_get_eapol(struct wpa_authenticator *wpa_auth,
const u8 *addr, wpa_eapol_variable var)
{
- if (wpa_auth->cb.get_eapol == NULL)
+ if (wpa_auth->cb->get_eapol == NULL)
return -1;
- return wpa_auth->cb.get_eapol(wpa_auth->cb.ctx, addr, var);
+ return wpa_auth->cb->get_eapol(wpa_auth->cb_ctx, addr, var);
}
static inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth,
const u8 *addr,
const u8 *p2p_dev_addr,
- const u8 *prev_psk)
+ const u8 *prev_psk, size_t *psk_len,
+ int *vlan_id)
{
- if (wpa_auth->cb.get_psk == NULL)
+ if (wpa_auth->cb->get_psk == NULL)
return NULL;
- return wpa_auth->cb.get_psk(wpa_auth->cb.ctx, addr, p2p_dev_addr,
- prev_psk);
+ return wpa_auth->cb->get_psk(wpa_auth->cb_ctx, addr, p2p_dev_addr,
+ prev_psk, psk_len, vlan_id);
}
static inline int wpa_auth_get_msk(struct wpa_authenticator *wpa_auth,
const u8 *addr, u8 *msk, size_t *len)
{
- if (wpa_auth->cb.get_msk == NULL)
+ if (wpa_auth->cb->get_msk == NULL)
return -1;
- return wpa_auth->cb.get_msk(wpa_auth->cb.ctx, addr, msk, len);
+ return wpa_auth->cb->get_msk(wpa_auth->cb_ctx, addr, msk, len);
}
@@ -128,19 +140,19 @@ static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth,
enum wpa_alg alg, const u8 *addr, int idx,
u8 *key, size_t key_len)
{
- if (wpa_auth->cb.set_key == NULL)
+ if (wpa_auth->cb->set_key == NULL)
return -1;
- return wpa_auth->cb.set_key(wpa_auth->cb.ctx, vlan_id, alg, addr, idx,
- key, key_len);
+ return wpa_auth->cb->set_key(wpa_auth->cb_ctx, vlan_id, alg, addr, idx,
+ key, key_len);
}
static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth,
const u8 *addr, int idx, u8 *seq)
{
- if (wpa_auth->cb.get_seqnum == NULL)
+ if (wpa_auth->cb->get_seqnum == NULL)
return -1;
- return wpa_auth->cb.get_seqnum(wpa_auth->cb.ctx, addr, idx, seq);
+ return wpa_auth->cb->get_seqnum(wpa_auth->cb_ctx, addr, idx, seq);
}
@@ -148,10 +160,10 @@ static inline int
wpa_auth_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr,
const u8 *data, size_t data_len, int encrypt)
{
- if (wpa_auth->cb.send_eapol == NULL)
+ if (wpa_auth->cb->send_eapol == NULL)
return -1;
- return wpa_auth->cb.send_eapol(wpa_auth->cb.ctx, addr, data, data_len,
- encrypt);
+ return wpa_auth->cb->send_eapol(wpa_auth->cb_ctx, addr, data, data_len,
+ encrypt);
}
@@ -159,9 +171,9 @@ wpa_auth_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr,
static inline int wpa_auth_start_ampe(struct wpa_authenticator *wpa_auth,
const u8 *addr)
{
- if (wpa_auth->cb.start_ampe == NULL)
+ if (wpa_auth->cb->start_ampe == NULL)
return -1;
- return wpa_auth->cb.start_ampe(wpa_auth->cb.ctx, addr);
+ return wpa_auth->cb->start_ampe(wpa_auth->cb_ctx, addr);
}
#endif /* CONFIG_MESH */
@@ -170,9 +182,9 @@ int wpa_auth_for_each_sta(struct wpa_authenticator *wpa_auth,
int (*cb)(struct wpa_state_machine *sm, void *ctx),
void *cb_ctx)
{
- if (wpa_auth->cb.for_each_sta == NULL)
+ if (wpa_auth->cb->for_each_sta == NULL)
return 0;
- return wpa_auth->cb.for_each_sta(wpa_auth->cb.ctx, cb, cb_ctx);
+ return wpa_auth->cb->for_each_sta(wpa_auth->cb_ctx, cb, cb_ctx);
}
@@ -180,18 +192,18 @@ int wpa_auth_for_each_auth(struct wpa_authenticator *wpa_auth,
int (*cb)(struct wpa_authenticator *a, void *ctx),
void *cb_ctx)
{
- if (wpa_auth->cb.for_each_auth == NULL)
+ if (wpa_auth->cb->for_each_auth == NULL)
return 0;
- return wpa_auth->cb.for_each_auth(wpa_auth->cb.ctx, cb, cb_ctx);
+ return wpa_auth->cb->for_each_auth(wpa_auth->cb_ctx, cb, cb_ctx);
}
void wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr,
logger_level level, const char *txt)
{
- if (wpa_auth->cb.logger == NULL)
+ if (wpa_auth->cb->logger == NULL)
return;
- wpa_auth->cb.logger(wpa_auth->cb.ctx, addr, level, txt);
+ wpa_auth->cb->logger(wpa_auth->cb_ctx, addr, level, txt);
}
@@ -202,7 +214,7 @@ void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr,
int maxlen;
va_list ap;
- if (wpa_auth->cb.logger == NULL)
+ if (wpa_auth->cb->logger == NULL)
return;
maxlen = os_strlen(fmt) + 100;
@@ -221,30 +233,33 @@ void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr,
static void wpa_sta_disconnect(struct wpa_authenticator *wpa_auth,
- const u8 *addr)
+ const u8 *addr, u16 reason)
{
- if (wpa_auth->cb.disconnect == NULL)
+ if (wpa_auth->cb->disconnect == NULL)
return;
- wpa_printf(MSG_DEBUG, "wpa_sta_disconnect STA " MACSTR, MAC2STR(addr));
- wpa_auth->cb.disconnect(wpa_auth->cb.ctx, addr,
- WLAN_REASON_PREV_AUTH_NOT_VALID);
+ wpa_printf(MSG_DEBUG, "wpa_sta_disconnect STA " MACSTR " (reason %u)",
+ MAC2STR(addr), reason);
+ wpa_auth->cb->disconnect(wpa_auth->cb_ctx, addr, reason);
}
-static int wpa_use_aes_cmac(struct wpa_state_machine *sm)
+#ifdef CONFIG_OCV
+static int wpa_channel_info(struct wpa_authenticator *wpa_auth,
+ struct wpa_channel_info *ci)
{
- int ret = 0;
-#ifdef CONFIG_IEEE80211R
- if (wpa_key_mgmt_ft(sm->wpa_key_mgmt))
- ret = 1;
-#endif /* CONFIG_IEEE80211R */
-#ifdef CONFIG_IEEE80211W
- if (wpa_key_mgmt_sha256(sm->wpa_key_mgmt))
- ret = 1;
-#endif /* CONFIG_IEEE80211W */
- if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN)
- ret = 1;
- return ret;
+ if (!wpa_auth->cb->channel_info)
+ return -1;
+ return wpa_auth->cb->channel_info(wpa_auth->cb_ctx, ci);
+}
+#endif /* CONFIG_OCV */
+
+
+static int wpa_auth_update_vlan(struct wpa_authenticator *wpa_auth,
+ const u8 *addr, int vlan_id)
+{
+ if (!wpa_auth->cb->update_vlan)
+ return -1;
+ return wpa_auth->cb->update_vlan(wpa_auth->cb_ctx, addr, vlan_id);
}
@@ -307,6 +322,19 @@ static void wpa_rekey_ptk(void *eloop_ctx, void *timeout_ctx)
}
+void wpa_auth_set_ptk_rekey_timer(struct wpa_state_machine *sm)
+{
+ if (sm && sm->wpa_auth->conf.wpa_ptk_rekey) {
+ wpa_printf(MSG_DEBUG, "WPA: Start PTK rekeying timer for "
+ MACSTR " (%d seconds)", MAC2STR(sm->addr),
+ sm->wpa_auth->conf.wpa_ptk_rekey);
+ eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
+ eloop_register_timeout(sm->wpa_auth->conf.wpa_ptk_rekey, 0,
+ wpa_rekey_ptk, sm->wpa_auth, sm);
+ }
+}
+
+
static int wpa_auth_pmksa_clear_cb(struct wpa_state_machine *sm, void *ctx)
{
if (sm->pmksa == ctx)
@@ -342,6 +370,10 @@ static int wpa_group_init_gmk_and_counter(struct wpa_authenticator *wpa_auth,
wpa_get_ntp_timestamp(buf + ETH_ALEN);
ptr = (unsigned long) group;
os_memcpy(buf + ETH_ALEN + 8, &ptr, sizeof(ptr));
+#ifdef TEST_FUZZ
+ os_memset(buf + ETH_ALEN, 0xab, 8);
+ os_memset(buf + ETH_ALEN + 8, 0xcd, sizeof(ptr));
+#endif /* TEST_FUZZ */
if (random_get_bytes(rkey, sizeof(rkey)) < 0)
return -1;
@@ -411,7 +443,8 @@ static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth,
*/
struct wpa_authenticator * wpa_init(const u8 *addr,
struct wpa_auth_config *conf,
- struct wpa_auth_callbacks *cb)
+ const struct wpa_auth_callbacks *cb,
+ void *cb_ctx)
{
struct wpa_authenticator *wpa_auth;
@@ -420,7 +453,8 @@ struct wpa_authenticator * wpa_init(const u8 *addr,
return NULL;
os_memcpy(wpa_auth->addr, addr, ETH_ALEN);
os_memcpy(&wpa_auth->conf, conf, sizeof(*conf));
- os_memcpy(&wpa_auth->cb, cb, sizeof(*cb));
+ wpa_auth->cb = cb;
+ wpa_auth->cb_ctx = cb_ctx;
if (wpa_auth_gen_wpa_ie(wpa_auth)) {
wpa_printf(MSG_ERROR, "Could not generate WPA IE.");
@@ -445,7 +479,7 @@ struct wpa_authenticator * wpa_init(const u8 *addr,
return NULL;
}
-#ifdef CONFIG_IEEE80211R
+#ifdef CONFIG_IEEE80211R_AP
wpa_auth->ft_pmk_cache = wpa_ft_pmk_cache_init();
if (wpa_auth->ft_pmk_cache == NULL) {
wpa_printf(MSG_ERROR, "FT PMK cache initialization failed.");
@@ -455,7 +489,7 @@ struct wpa_authenticator * wpa_init(const u8 *addr,
os_free(wpa_auth);
return NULL;
}
-#endif /* CONFIG_IEEE80211R */
+#endif /* CONFIG_IEEE80211R_AP */
if (wpa_auth->conf.wpa_gmk_rekey) {
eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0,
@@ -508,17 +542,13 @@ void wpa_deinit(struct wpa_authenticator *wpa_auth)
eloop_cancel_timeout(wpa_rekey_gmk, wpa_auth, NULL);
eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
-#ifdef CONFIG_PEERKEY
- while (wpa_auth->stsl_negotiations)
- wpa_stsl_remove(wpa_auth, wpa_auth->stsl_negotiations);
-#endif /* CONFIG_PEERKEY */
-
pmksa_cache_auth_deinit(wpa_auth->pmksa);
-#ifdef CONFIG_IEEE80211R
+#ifdef CONFIG_IEEE80211R_AP
wpa_ft_pmk_cache_deinit(wpa_auth->ft_pmk_cache);
wpa_auth->ft_pmk_cache = NULL;
-#endif /* CONFIG_IEEE80211R */
+ wpa_ft_deinit(wpa_auth);
+#endif /* CONFIG_IEEE80211R_AP */
#ifdef CONFIG_P2P
bitfield_free(wpa_auth->ip_pool);
@@ -601,16 +631,28 @@ int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,
if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL)
return -1;
-#ifdef CONFIG_IEEE80211R
+#ifdef CONFIG_IEEE80211R_AP
if (sm->ft_completed) {
wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
"FT authentication already completed - do not "
"start 4-way handshake");
/* Go to PTKINITDONE state to allow GTK rekeying */
sm->wpa_ptk_state = WPA_PTK_PTKINITDONE;
+ sm->Pair = TRUE;
+ return 0;
+ }
+#endif /* CONFIG_IEEE80211R_AP */
+
+#ifdef CONFIG_FILS
+ if (sm->fils_completed) {
+ wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
+ "FILS authentication already completed - do not start 4-way handshake");
+ /* Go to PTKINITDONE state to allow GTK rekeying */
+ sm->wpa_ptk_state = WPA_PTK_PTKINITDONE;
+ sm->Pair = TRUE;
return 0;
}
-#endif /* CONFIG_IEEE80211R */
+#endif /* CONFIG_FILS */
if (sm->started) {
os_memset(&sm->key_replay, 0, sizeof(sm->key_replay));
@@ -662,14 +704,17 @@ static void wpa_free_sta_sm(struct wpa_state_machine *sm)
sm->group->GKeyDoneStations--;
sm->GUpdateStationKeys = FALSE;
}
-#ifdef CONFIG_IEEE80211R
+#ifdef CONFIG_IEEE80211R_AP
os_free(sm->assoc_resp_ftie);
wpabuf_free(sm->ft_pending_req_ies);
-#endif /* CONFIG_IEEE80211R */
+#endif /* CONFIG_IEEE80211R_AP */
os_free(sm->last_rx_eapol_key);
os_free(sm->wpa_ie);
wpa_group_put(sm->wpa_auth, sm->group);
- os_free(sm);
+#ifdef CONFIG_DPP2
+ wpabuf_clear_free(sm->dpp_z);
+#endif /* CONFIG_DPP2 */
+ bin_clear_free(sm, sizeof(*sm));
}
@@ -682,15 +727,19 @@ void wpa_auth_sta_deinit(struct wpa_state_machine *sm)
wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
"strict rekeying - force GTK rekey since STA "
"is leaving");
- eloop_cancel_timeout(wpa_rekey_gtk, sm->wpa_auth, NULL);
- eloop_register_timeout(0, 500000, wpa_rekey_gtk, sm->wpa_auth,
- NULL);
+ if (eloop_deplete_timeout(0, 500000, wpa_rekey_gtk,
+ sm->wpa_auth, NULL) == -1)
+ eloop_register_timeout(0, 500000, wpa_rekey_gtk, sm->wpa_auth,
+ NULL);
}
eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm);
sm->pending_1_of_4_timeout = 0;
eloop_cancel_timeout(wpa_sm_call_step, sm, NULL);
eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
+#ifdef CONFIG_IEEE80211R_AP
+ wpa_ft_sta_deinit(sm);
+#endif /* CONFIG_IEEE80211R_AP */
if (sm->in_step_loop) {
/* Must not free state machine while wpa_sm_step() is running.
* Freeing will be completed in the end of wpa_sm_step(). */
@@ -741,7 +790,7 @@ static void wpa_replay_counter_mark_invalid(struct wpa_key_replay_counter *ctr,
}
-#ifdef CONFIG_IEEE80211R
+#ifdef CONFIG_IEEE80211R_AP
static int ft_check_msg_2_of_4(struct wpa_authenticator *wpa_auth,
struct wpa_state_machine *sm,
struct wpa_eapol_ie_parse *kde)
@@ -788,7 +837,7 @@ static int ft_check_msg_2_of_4(struct wpa_authenticator *wpa_auth,
return 0;
}
-#endif /* CONFIG_IEEE80211R */
+#endif /* CONFIG_IEEE80211R_AP */
static int wpa_receive_error_report(struct wpa_authenticator *wpa_auth,
@@ -830,29 +879,44 @@ static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data,
struct wpa_ptk PTK;
int ok = 0;
const u8 *pmk = NULL;
- unsigned int pmk_len;
+ size_t pmk_len;
+ int vlan_id = 0;
+ os_memset(&PTK, 0, sizeof(PTK));
for (;;) {
- if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) {
+ if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
+ !wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr,
- sm->p2p_dev_addr, pmk);
+ sm->p2p_dev_addr, pmk, &pmk_len,
+ &vlan_id);
if (pmk == NULL)
break;
- pmk_len = PMK_LEN;
+#ifdef CONFIG_IEEE80211R_AP
+ if (wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) {
+ os_memcpy(sm->xxkey, pmk, pmk_len);
+ sm->xxkey_len = pmk_len;
+ }
+#endif /* CONFIG_IEEE80211R_AP */
} else {
pmk = sm->PMK;
pmk_len = sm->pmk_len;
}
- wpa_derive_ptk(sm, sm->alt_SNonce, pmk, pmk_len, &PTK);
+ if (wpa_derive_ptk(sm, sm->alt_SNonce, pmk, pmk_len, &PTK) < 0)
+ break;
- if (wpa_verify_key_mic(sm->wpa_key_mgmt, &PTK, data, data_len)
- == 0) {
+ if (wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK,
+ data, data_len) == 0) {
+ if (sm->PMK != pmk) {
+ os_memcpy(sm->PMK, pmk, pmk_len);
+ sm->pmk_len = pmk_len;
+ }
ok = 1;
break;
}
- if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt))
+ if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
+ wpa_key_mgmt_sae(sm->wpa_key_mgmt))
break;
}
@@ -865,6 +929,11 @@ static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data,
wpa_printf(MSG_DEBUG,
"WPA: Earlier SNonce resulted in matching MIC");
sm->alt_snonce_valid = 0;
+
+ if (vlan_id && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
+ wpa_auth_update_vlan(sm->wpa_auth, sm->addr, vlan_id) < 0)
+ return -1;
+
os_memcpy(sm->SNonce, sm->alt_SNonce, WPA_NONCE_LEN);
os_memcpy(&sm->PTK, &PTK, sizeof(PTK));
sm->PTK_valid = TRUE;
@@ -879,39 +948,41 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
{
struct ieee802_1x_hdr *hdr;
struct wpa_eapol_key *key;
- struct wpa_eapol_key_192 *key192;
u16 key_info, key_data_length;
- enum { PAIRWISE_2, PAIRWISE_4, GROUP_2, REQUEST,
- SMK_M1, SMK_M3, SMK_ERROR } msg;
+ enum { PAIRWISE_2, PAIRWISE_4, GROUP_2, REQUEST } msg;
char *msgtxt;
struct wpa_eapol_ie_parse kde;
- int ft;
- const u8 *eapol_key_ie, *key_data;
- size_t eapol_key_ie_len, keyhdrlen, mic_len;
+ const u8 *key_data;
+ size_t keyhdrlen, mic_len;
+ u8 *mic;
if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL)
return;
+ wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL data", data, data_len);
- mic_len = wpa_mic_len(sm->wpa_key_mgmt);
- keyhdrlen = mic_len == 24 ? sizeof(*key192) : sizeof(*key);
+ mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
+ keyhdrlen = sizeof(*key) + mic_len + 2;
- if (data_len < sizeof(*hdr) + keyhdrlen)
+ if (data_len < sizeof(*hdr) + keyhdrlen) {
+ wpa_printf(MSG_DEBUG, "WPA: Ignore too short EAPOL-Key frame");
return;
+ }
hdr = (struct ieee802_1x_hdr *) data;
key = (struct wpa_eapol_key *) (hdr + 1);
- key192 = (struct wpa_eapol_key_192 *) (hdr + 1);
+ mic = (u8 *) (key + 1);
key_info = WPA_GET_BE16(key->key_info);
- if (mic_len == 24) {
- key_data = (const u8 *) (key192 + 1);
- key_data_length = WPA_GET_BE16(key192->key_data_length);
- } else {
- key_data = (const u8 *) (key + 1);
- key_data_length = WPA_GET_BE16(key->key_data_length);
- }
+ key_data = mic + mic_len + 2;
+ key_data_length = WPA_GET_BE16(mic + mic_len);
wpa_printf(MSG_DEBUG, "WPA: Received EAPOL-Key from " MACSTR
- " key_info=0x%x type=%u key_data_length=%u",
- MAC2STR(sm->addr), key_info, key->type, key_data_length);
+ " key_info=0x%x type=%u mic_len=%u key_data_length=%u",
+ MAC2STR(sm->addr), key_info, key->type,
+ (unsigned int) mic_len, key_data_length);
+ wpa_hexdump(MSG_MSGDUMP,
+ "WPA: EAPOL-Key header (ending before Key MIC)",
+ key, sizeof(*key));
+ wpa_hexdump(MSG_MSGDUMP, "WPA: EAPOL-Key Key MIC",
+ mic, mic_len);
if (key_data_length > data_len - sizeof(*hdr) - keyhdrlen) {
wpa_printf(MSG_INFO, "WPA: Invalid EAPOL-Key frame - "
"key_data overflow (%d > %lu)",
@@ -952,25 +1023,20 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
/* FIX: verify that the EAPOL-Key frame was encrypted if pairwise keys
* are set */
- if ((key_info & (WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_REQUEST)) ==
- (WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_REQUEST)) {
- if (key_info & WPA_KEY_INFO_ERROR) {
- msg = SMK_ERROR;
- msgtxt = "SMK Error";
- } else {
- msg = SMK_M1;
- msgtxt = "SMK M1";
- }
- } else if (key_info & WPA_KEY_INFO_SMK_MESSAGE) {
- msg = SMK_M3;
- msgtxt = "SMK M3";
- } else if (key_info & WPA_KEY_INFO_REQUEST) {
+ if (key_info & WPA_KEY_INFO_SMK_MESSAGE) {
+ wpa_printf(MSG_DEBUG, "WPA: Ignore SMK message");
+ return;
+ }
+
+ if (key_info & WPA_KEY_INFO_REQUEST) {
msg = REQUEST;
msgtxt = "Request";
} else if (!(key_info & WPA_KEY_INFO_KEY_TYPE)) {
msg = GROUP_2;
msgtxt = "2/2 Group";
- } else if (key_data_length == 0) {
+ } else if (key_data_length == 0 ||
+ (mic_len == 0 && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) &&
+ key_data_length == AES_BLOCK_SIZE)) {
msg = PAIRWISE_4;
msgtxt = "4/4 Pairwise";
} else {
@@ -978,15 +1044,13 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
msgtxt = "2/4 Pairwise";
}
- /* TODO: key_info type validation for PeerKey */
if (msg == REQUEST || msg == PAIRWISE_2 || msg == PAIRWISE_4 ||
msg == GROUP_2) {
u16 ver = key_info & WPA_KEY_INFO_TYPE_MASK;
if (sm->pairwise == WPA_CIPHER_CCMP ||
sm->pairwise == WPA_CIPHER_GCMP) {
- if (wpa_use_aes_cmac(sm) &&
- sm->wpa_key_mgmt != WPA_KEY_MGMT_OSEN &&
- !wpa_key_mgmt_suite_b(sm->wpa_key_mgmt) &&
+ if (wpa_use_cmac(sm->wpa_key_mgmt) &&
+ !wpa_use_akm_defined(sm->wpa_key_mgmt) &&
ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
wpa_auth_logger(wpa_auth, sm->addr,
LOGGER_WARNING,
@@ -996,7 +1060,8 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
return;
}
- if (!wpa_use_aes_cmac(sm) &&
+ if (!wpa_use_cmac(sm->wpa_key_mgmt) &&
+ !wpa_use_akm_defined(sm->wpa_key_mgmt) &&
ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
wpa_auth_logger(wpa_auth, sm->addr,
LOGGER_WARNING,
@@ -1006,7 +1071,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
}
}
- if (wpa_key_mgmt_suite_b(sm->wpa_key_mgmt) &&
+ if (wpa_use_akm_defined(sm->wpa_key_mgmt) &&
ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) {
wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING,
"did not use EAPOL-Key descriptor version 0 as required for AKM-defined cases");
@@ -1094,6 +1159,15 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
}
continue_processing:
+#ifdef CONFIG_FILS
+ if (sm->wpa == WPA_VERSION_WPA2 && mic_len == 0 &&
+ !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
+ wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
+ "WPA: Encr Key Data bit not set even though AEAD cipher is supposed to be used - drop frame");
+ return;
+ }
+#endif /* CONFIG_FILS */
+
switch (msg) {
case PAIRWISE_2:
if (sm->wpa_ptk_state != WPA_PTK_PTKSTART &&
@@ -1121,70 +1195,10 @@ continue_processing:
"collect more entropy for random number "
"generation");
random_mark_pool_ready();
- wpa_sta_disconnect(wpa_auth, sm->addr);
+ wpa_sta_disconnect(wpa_auth, sm->addr,
+ WLAN_REASON_PREV_AUTH_NOT_VALID);
return;
}
- if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) {
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
- "received EAPOL-Key msg 2/4 with "
- "invalid Key Data contents");
- return;
- }
- if (kde.rsn_ie) {
- eapol_key_ie = kde.rsn_ie;
- eapol_key_ie_len = kde.rsn_ie_len;
- } else if (kde.osen) {
- eapol_key_ie = kde.osen;
- eapol_key_ie_len = kde.osen_len;
- } else {
- eapol_key_ie = kde.wpa_ie;
- eapol_key_ie_len = kde.wpa_ie_len;
- }
- ft = sm->wpa == WPA_VERSION_WPA2 &&
- wpa_key_mgmt_ft(sm->wpa_key_mgmt);
- if (sm->wpa_ie == NULL ||
- wpa_compare_rsn_ie(ft,
- sm->wpa_ie, sm->wpa_ie_len,
- eapol_key_ie, eapol_key_ie_len)) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
- "WPA IE from (Re)AssocReq did not "
- "match with msg 2/4");
- if (sm->wpa_ie) {
- wpa_hexdump(MSG_DEBUG, "WPA IE in AssocReq",
- sm->wpa_ie, sm->wpa_ie_len);
- }
- wpa_hexdump(MSG_DEBUG, "WPA IE in msg 2/4",
- eapol_key_ie, eapol_key_ie_len);
- /* MLME-DEAUTHENTICATE.request */
- wpa_sta_disconnect(wpa_auth, sm->addr);
- return;
- }
-#ifdef CONFIG_IEEE80211R
- if (ft && ft_check_msg_2_of_4(wpa_auth, sm, &kde) < 0) {
- wpa_sta_disconnect(wpa_auth, sm->addr);
- return;
- }
-#endif /* CONFIG_IEEE80211R */
-#ifdef CONFIG_P2P
- if (kde.ip_addr_req && kde.ip_addr_req[0] &&
- wpa_auth->ip_pool && WPA_GET_BE32(sm->ip_addr) == 0) {
- int idx;
- wpa_printf(MSG_DEBUG, "P2P: IP address requested in "
- "EAPOL-Key exchange");
- idx = bitfield_get_first_zero(wpa_auth->ip_pool);
- if (idx >= 0) {
- u32 start = WPA_GET_BE32(wpa_auth->conf.
- ip_addr_start);
- bitfield_set(wpa_auth->ip_pool, idx);
- WPA_PUT_BE32(sm->ip_addr, start + idx);
- wpa_printf(MSG_DEBUG, "P2P: Assigned IP "
- "address %u.%u.%u.%u to " MACSTR,
- sm->ip_addr[0], sm->ip_addr[1],
- sm->ip_addr[2], sm->ip_addr[3],
- MAC2STR(sm->addr));
- }
- }
-#endif /* CONFIG_P2P */
break;
case PAIRWISE_4:
if (sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING ||
@@ -1206,28 +1220,6 @@ continue_processing:
return;
}
break;
-#ifdef CONFIG_PEERKEY
- case SMK_M1:
- case SMK_M3:
- case SMK_ERROR:
- if (!wpa_auth->conf.peerkey) {
- wpa_printf(MSG_DEBUG, "RSN: SMK M1/M3/Error, but "
- "PeerKey use disabled - ignoring message");
- return;
- }
- if (!sm->PTK_valid) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
- "received EAPOL-Key msg SMK in "
- "invalid state - dropped");
- return;
- }
- break;
-#else /* CONFIG_PEERKEY */
- case SMK_M1:
- case SMK_M3:
- case SMK_ERROR:
- return; /* STSL disabled - ignore SMK messages */
-#endif /* CONFIG_PEERKEY */
case REQUEST:
break;
}
@@ -1241,22 +1233,55 @@ continue_processing:
return;
}
- if (!(key_info & WPA_KEY_INFO_MIC)) {
+ if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
+ !(key_info & WPA_KEY_INFO_MIC)) {
wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
"received invalid EAPOL-Key: Key MIC not set");
return;
}
+#ifdef CONFIG_FILS
+ if (wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
+ (key_info & WPA_KEY_INFO_MIC)) {
+ wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ "received invalid EAPOL-Key: Key MIC set");
+ return;
+ }
+#endif /* CONFIG_FILS */
+
sm->MICVerified = FALSE;
if (sm->PTK_valid && !sm->update_snonce) {
- if (wpa_verify_key_mic(sm->wpa_key_mgmt, &sm->PTK, data,
- data_len) &&
+ if (mic_len &&
+ wpa_verify_key_mic(sm->wpa_key_mgmt, sm->pmk_len, &sm->PTK,
+ data, data_len) &&
(msg != PAIRWISE_4 || !sm->alt_snonce_valid ||
wpa_try_alt_snonce(sm, data, data_len))) {
wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
"received EAPOL-Key with invalid MIC");
+#ifdef TEST_FUZZ
+ wpa_printf(MSG_INFO,
+ "TEST: Ignore Key MIC failure for fuzz testing");
+ goto continue_fuzz;
+#endif /* TEST_FUZZ */
+ return;
+ }
+#ifdef CONFIG_FILS
+ if (!mic_len &&
+ wpa_aead_decrypt(sm, &sm->PTK, data, data_len,
+ &key_data_length) < 0) {
+ wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ "received EAPOL-Key with invalid MIC");
+#ifdef TEST_FUZZ
+ wpa_printf(MSG_INFO,
+ "TEST: Ignore Key MIC failure for fuzz testing");
+ goto continue_fuzz;
+#endif /* TEST_FUZZ */
return;
}
+#endif /* CONFIG_FILS */
+#ifdef TEST_FUZZ
+ continue_fuzz:
+#endif /* TEST_FUZZ */
sm->MICVerified = TRUE;
eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm);
sm->pending_1_of_4_timeout = 0;
@@ -1279,12 +1304,7 @@ continue_processing:
* even though MAC address KDE is not normally encrypted,
* supplicant is allowed to encrypt it.
*/
- if (msg == SMK_ERROR) {
-#ifdef CONFIG_PEERKEY
- wpa_smk_error(wpa_auth, sm, key_data, key_data_length);
-#endif /* CONFIG_PEERKEY */
- return;
- } else if (key_info & WPA_KEY_INFO_ERROR) {
+ if (key_info & WPA_KEY_INFO_ERROR) {
if (wpa_receive_error_report(
wpa_auth, sm,
!(key_info & WPA_KEY_INFO_KEY_TYPE)) > 0)
@@ -1294,11 +1314,6 @@ continue_processing:
"received EAPOL-Key Request for new "
"4-Way Handshake");
wpa_request_new_ptk(sm);
-#ifdef CONFIG_PEERKEY
- } else if (msg == SMK_M1) {
- wpa_smk_m1(wpa_auth, sm, key, key_data,
- key_data_length);
-#endif /* CONFIG_PEERKEY */
} else if (key_data_length > 0 &&
wpa_parse_kde_ies(key_data, key_data_length,
&kde) == 0 &&
@@ -1337,18 +1352,10 @@ continue_processing:
wpa_replay_counter_mark_invalid(sm->key_replay, NULL);
}
-#ifdef CONFIG_PEERKEY
- if (msg == SMK_M3) {
- wpa_smk_m3(wpa_auth, sm, key, key_data, key_data_length);
- return;
- }
-#endif /* CONFIG_PEERKEY */
-
os_free(sm->last_rx_eapol_key);
- sm->last_rx_eapol_key = os_malloc(data_len);
+ sm->last_rx_eapol_key = os_memdup(data, data_len);
if (sm->last_rx_eapol_key == NULL)
return;
- os_memcpy(sm->last_rx_eapol_key, data, data_len);
sm->last_rx_eapol_key_len = data_len;
sm->rx_eapol_key_secure = !!(key_info & WPA_KEY_INFO_SECURE);
@@ -1363,7 +1370,7 @@ continue_processing:
static int wpa_gmk_to_gtk(const u8 *gmk, const char *label, const u8 *addr,
const u8 *gnonce, u8 *gtk, size_t gtk_len)
{
- u8 data[ETH_ALEN + WPA_NONCE_LEN + 8 + 16];
+ u8 data[ETH_ALEN + WPA_NONCE_LEN + 8 + WPA_GTK_MAX_LEN];
u8 *pos;
int ret = 0;
@@ -1374,21 +1381,33 @@ static int wpa_gmk_to_gtk(const u8 *gmk, const char *label, const u8 *addr,
* is done only at the Authenticator and as such, does not need to be
* exactly same.
*/
+ os_memset(data, 0, sizeof(data));
os_memcpy(data, addr, ETH_ALEN);
os_memcpy(data + ETH_ALEN, gnonce, WPA_NONCE_LEN);
pos = data + ETH_ALEN + WPA_NONCE_LEN;
wpa_get_ntp_timestamp(pos);
+#ifdef TEST_FUZZ
+ os_memset(pos, 0xef, 8);
+#endif /* TEST_FUZZ */
pos += 8;
- if (random_get_bytes(pos, 16) < 0)
+ if (random_get_bytes(pos, gtk_len) < 0)
ret = -1;
-#ifdef CONFIG_IEEE80211W
- sha256_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data), gtk, gtk_len);
-#else /* CONFIG_IEEE80211W */
- if (sha1_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data), gtk, gtk_len)
- < 0)
+#ifdef CONFIG_SHA384
+ if (sha384_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data),
+ gtk, gtk_len) < 0)
ret = -1;
-#endif /* CONFIG_IEEE80211W */
+#else /* CONFIG_SHA384 */
+#ifdef CONFIG_SHA256
+ if (sha256_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data),
+ gtk, gtk_len) < 0)
+ ret = -1;
+#else /* CONFIG_SHA256 */
+ if (sha1_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data),
+ gtk, gtk_len) < 0)
+ ret = -1;
+#endif /* CONFIG_SHA256 */
+#endif /* CONFIG_SHA384 */
return ret;
}
@@ -1414,26 +1433,24 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
{
struct ieee802_1x_hdr *hdr;
struct wpa_eapol_key *key;
- struct wpa_eapol_key_192 *key192;
size_t len, mic_len, keyhdrlen;
int alg;
int key_data_len, pad_len = 0;
u8 *buf, *pos;
int version, pairwise;
int i;
- u8 *key_data;
+ u8 *key_mic, *key_data;
- mic_len = wpa_mic_len(sm->wpa_key_mgmt);
- keyhdrlen = mic_len == 24 ? sizeof(*key192) : sizeof(*key);
+ mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
+ keyhdrlen = sizeof(*key) + mic_len + 2;
len = sizeof(struct ieee802_1x_hdr) + keyhdrlen;
if (force_version)
version = force_version;
- else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN ||
- wpa_key_mgmt_suite_b(sm->wpa_key_mgmt))
+ else if (wpa_use_akm_defined(sm->wpa_key_mgmt))
version = WPA_KEY_INFO_TYPE_AKM_DEFINED;
- else if (wpa_use_aes_cmac(sm))
+ else if (wpa_use_cmac(sm->wpa_key_mgmt))
version = WPA_KEY_INFO_TYPE_AES_128_CMAC;
else if (sm->pairwise != WPA_CIPHER_TKIP)
version = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
@@ -1455,8 +1472,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
key_data_len = kde_len;
if ((version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
- sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN ||
- wpa_key_mgmt_suite_b(sm->wpa_key_mgmt) ||
+ wpa_use_aes_key_wrap(sm->wpa_key_mgmt) ||
version == WPA_KEY_INFO_TYPE_AES_128_CMAC) && encr) {
pad_len = key_data_len % 8;
if (pad_len)
@@ -1465,6 +1481,8 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
}
len += key_data_len;
+ if (!mic_len && encr)
+ len += AES_BLOCK_SIZE;
hdr = os_zalloc(len);
if (hdr == NULL)
@@ -1473,7 +1491,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
hdr->type = IEEE802_1X_TYPE_EAPOL_KEY;
hdr->length = host_to_be16(len - sizeof(*hdr));
key = (struct wpa_eapol_key *) (hdr + 1);
- key192 = (struct wpa_eapol_key_192 *) (hdr + 1);
+ key_mic = (u8 *) (key + 1);
key_data = ((u8 *) (hdr + 1)) + keyhdrlen;
key->type = sm->wpa == WPA_VERSION_WPA2 ?
@@ -1486,11 +1504,11 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
WPA_PUT_BE16(key->key_info, key_info);
alg = pairwise ? sm->pairwise : wpa_auth->conf.wpa_group;
- WPA_PUT_BE16(key->key_length, wpa_cipher_key_len(alg));
- if (key_info & WPA_KEY_INFO_SMK_MESSAGE)
+ if (sm->wpa == WPA_VERSION_WPA2 && !pairwise)
WPA_PUT_BE16(key->key_length, 0);
+ else
+ WPA_PUT_BE16(key->key_length, wpa_cipher_key_len(alg));
- /* FIX: STSL: what to use as key_replay_counter? */
for (i = RSNA_MAX_EAPOL_RETRIES - 1; i > 0; i--) {
sm->key_replay[i].valid = sm->key_replay[i - 1].valid;
os_memcpy(sm->key_replay[i].counter,
@@ -1512,10 +1530,31 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
if (kde && !encr) {
os_memcpy(key_data, kde, kde_len);
- if (mic_len == 24)
- WPA_PUT_BE16(key192->key_data_length, kde_len);
- else
- WPA_PUT_BE16(key->key_data_length, kde_len);
+ WPA_PUT_BE16(key_mic + mic_len, kde_len);
+#ifdef CONFIG_FILS
+ } else if (!mic_len && kde) {
+ const u8 *aad[1];
+ size_t aad_len[1];
+
+ WPA_PUT_BE16(key_mic, AES_BLOCK_SIZE + kde_len);
+ wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data",
+ kde, kde_len);
+
+ wpa_hexdump_key(MSG_DEBUG, "WPA: KEK",
+ sm->PTK.kek, sm->PTK.kek_len);
+ /* AES-SIV AAD from EAPOL protocol version field (inclusive) to
+ * to Key Data (exclusive). */
+ aad[0] = (u8 *) hdr;
+ aad_len[0] = key_mic + 2 - (u8 *) hdr;
+ if (aes_siv_encrypt(sm->PTK.kek, sm->PTK.kek_len, kde, kde_len,
+ 1, aad, aad_len, key_mic + 2) < 0) {
+ wpa_printf(MSG_DEBUG, "WPA: AES-SIV encryption failed");
+ return;
+ }
+
+ wpa_hexdump(MSG_DEBUG, "WPA: Encrypted Key Data from SIV",
+ key_mic + 2, AES_BLOCK_SIZE + kde_len);
+#endif /* CONFIG_FILS */
} else if (encr && kde) {
buf = os_zalloc(key_data_len);
if (buf == NULL) {
@@ -1532,24 +1571,24 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data",
buf, key_data_len);
if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
- sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN ||
- wpa_key_mgmt_suite_b(sm->wpa_key_mgmt) ||
+ wpa_use_aes_key_wrap(sm->wpa_key_mgmt) ||
version == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
+ wpa_printf(MSG_DEBUG,
+ "WPA: Encrypt Key Data using AES-WRAP (KEK length %u)",
+ (unsigned int) sm->PTK.kek_len);
if (aes_wrap(sm->PTK.kek, sm->PTK.kek_len,
(key_data_len - 8) / 8, buf, key_data)) {
os_free(hdr);
os_free(buf);
return;
}
- if (mic_len == 24)
- WPA_PUT_BE16(key192->key_data_length,
- key_data_len);
- else
- WPA_PUT_BE16(key->key_data_length,
- key_data_len);
+ WPA_PUT_BE16(key_mic + mic_len, key_data_len);
#ifndef CONFIG_NO_RC4
} else if (sm->PTK.kek_len == 16) {
u8 ek[32];
+
+ wpa_printf(MSG_DEBUG,
+ "WPA: Encrypt Key Data using RC4");
os_memcpy(key->key_iv,
sm->group->Counter + WPA_NONCE_LEN - 16, 16);
inc_byte_array(sm->group->Counter, WPA_NONCE_LEN);
@@ -1557,12 +1596,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
os_memcpy(ek + 16, sm->PTK.kek, sm->PTK.kek_len);
os_memcpy(key_data, buf, key_data_len);
rc4_skip(ek, 32, 256, key_data, key_data_len);
- if (mic_len == 24)
- WPA_PUT_BE16(key192->key_data_length,
- key_data_len);
- else
- WPA_PUT_BE16(key->key_data_length,
- key_data_len);
+ WPA_PUT_BE16(key_mic + mic_len, key_data_len);
#endif /* CONFIG_NO_RC4 */
} else {
os_free(hdr);
@@ -1573,9 +1607,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
}
if (key_info & WPA_KEY_INFO_MIC) {
- u8 *key_mic;
-
- if (!sm->PTK_valid) {
+ if (!sm->PTK_valid || !mic_len) {
wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
"PTK not valid when sending EAPOL-Key "
"frame");
@@ -1583,10 +1615,12 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
return;
}
- key_mic = key192->key_mic; /* same offset for key and key192 */
- wpa_eapol_key_mic(sm->PTK.kck, sm->PTK.kck_len,
- sm->wpa_key_mgmt, version,
- (u8 *) hdr, len, key_mic);
+ if (wpa_eapol_key_mic(sm->PTK.kck, sm->PTK.kck_len,
+ sm->wpa_key_mgmt, version,
+ (u8 *) hdr, len, key_mic) < 0) {
+ os_free(hdr);
+ return;
+ }
#ifdef CONFIG_TESTING_OPTIONS
if (!pairwise &&
wpa_auth->conf.corrupt_gtk_rekey_mic_probability > 0.0 &&
@@ -1615,7 +1649,7 @@ static void wpa_send_eapol(struct wpa_authenticator *wpa_auth,
{
int timeout_ms;
int pairwise = key_info & WPA_KEY_INFO_KEY_TYPE;
- int ctr;
+ u32 ctr;
if (sm == NULL)
return;
@@ -1629,41 +1663,46 @@ static void wpa_send_eapol(struct wpa_authenticator *wpa_auth,
eapol_key_timeout_first_group;
else
timeout_ms = eapol_key_timeout_subseq;
+ if (wpa_auth->conf.wpa_disable_eapol_key_retries &&
+ (!pairwise || (key_info & WPA_KEY_INFO_MIC)))
+ timeout_ms = eapol_key_timeout_no_retrans;
if (pairwise && ctr == 1 && !(key_info & WPA_KEY_INFO_MIC))
sm->pending_1_of_4_timeout = 1;
+#ifdef TEST_FUZZ
+ timeout_ms = 1;
+#endif /* TEST_FUZZ */
wpa_printf(MSG_DEBUG, "WPA: Use EAPOL-Key timeout of %u ms (retry "
- "counter %d)", timeout_ms, ctr);
+ "counter %u)", timeout_ms, ctr);
eloop_register_timeout(timeout_ms / 1000, (timeout_ms % 1000) * 1000,
wpa_send_eapol_timeout, wpa_auth, sm);
}
-static int wpa_verify_key_mic(int akmp, struct wpa_ptk *PTK, u8 *data,
- size_t data_len)
+static int wpa_verify_key_mic(int akmp, size_t pmk_len, struct wpa_ptk *PTK,
+ u8 *data, size_t data_len)
{
struct ieee802_1x_hdr *hdr;
struct wpa_eapol_key *key;
- struct wpa_eapol_key_192 *key192;
u16 key_info;
int ret = 0;
- u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN];
- size_t mic_len = wpa_mic_len(akmp);
+ u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN], *mic_pos;
+ size_t mic_len = wpa_mic_len(akmp, pmk_len);
if (data_len < sizeof(*hdr) + sizeof(*key))
return -1;
hdr = (struct ieee802_1x_hdr *) data;
key = (struct wpa_eapol_key *) (hdr + 1);
- key192 = (struct wpa_eapol_key_192 *) (hdr + 1);
+ mic_pos = (u8 *) (key + 1);
key_info = WPA_GET_BE16(key->key_info);
- os_memcpy(mic, key192->key_mic, mic_len);
- os_memset(key192->key_mic, 0, mic_len);
+ os_memcpy(mic, mic_pos, mic_len);
+ os_memset(mic_pos, 0, mic_len);
if (wpa_eapol_key_mic(PTK->kck, PTK->kck_len, akmp,
key_info & WPA_KEY_INFO_TYPE_MASK,
- data, data_len, key192->key_mic) ||
- os_memcmp_const(mic, key192->key_mic, mic_len) != 0)
+ data, data_len, mic_pos) ||
+ os_memcmp_const(mic, mic_pos, mic_len) != 0)
ret = -1;
- os_memcpy(key192->key_mic, mic, mic_len);
+ os_memcpy(mic_pos, mic, mic_len);
return ret;
}
@@ -1672,7 +1711,10 @@ void wpa_remove_ptk(struct wpa_state_machine *sm)
{
sm->PTK_valid = FALSE;
os_memset(&sm->PTK, 0, sizeof(sm->PTK));
- wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 0, NULL, 0);
+ if (wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 0, NULL,
+ 0))
+ wpa_printf(MSG_DEBUG,
+ "RSN: PTK removal from the driver failed");
sm->pairwise_set = FALSE;
eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
}
@@ -1703,6 +1745,14 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event)
case WPA_DEAUTH:
case WPA_DISASSOC:
sm->DeauthenticationRequest = TRUE;
+#ifdef CONFIG_IEEE80211R_AP
+ os_memset(sm->PMK, 0, sizeof(sm->PMK));
+ sm->pmk_len = 0;
+ os_memset(sm->xxkey, 0, sizeof(sm->xxkey));
+ sm->xxkey_len = 0;
+ os_memset(sm->pmk_r1, 0, sizeof(sm->pmk_r1));
+ sm->pmk_r1_len = 0;
+#endif /* CONFIG_IEEE80211R_AP */
break;
case WPA_REAUTH:
case WPA_REAUTH_EAPOL:
@@ -1736,30 +1786,46 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event)
sm->ReAuthenticationRequest = TRUE;
break;
case WPA_ASSOC_FT:
-#ifdef CONFIG_IEEE80211R
+#ifdef CONFIG_IEEE80211R_AP
wpa_printf(MSG_DEBUG, "FT: Retry PTK configuration "
"after association");
wpa_ft_install_ptk(sm);
/* Using FT protocol, not WPA auth state machine */
sm->ft_completed = 1;
+ wpa_auth_set_ptk_rekey_timer(sm);
return 0;
-#else /* CONFIG_IEEE80211R */
+#else /* CONFIG_IEEE80211R_AP */
break;
-#endif /* CONFIG_IEEE80211R */
+#endif /* CONFIG_IEEE80211R_AP */
+ case WPA_ASSOC_FILS:
+#ifdef CONFIG_FILS
+ wpa_printf(MSG_DEBUG,
+ "FILS: TK configuration after association");
+ fils_set_tk(sm);
+ sm->fils_completed = 1;
+ return 0;
+#else /* CONFIG_FILS */
+ break;
+#endif /* CONFIG_FILS */
case WPA_DRV_STA_REMOVED:
sm->tk_already_set = FALSE;
return 0;
}
-#ifdef CONFIG_IEEE80211R
+#ifdef CONFIG_IEEE80211R_AP
sm->ft_completed = 0;
-#endif /* CONFIG_IEEE80211R */
+#endif /* CONFIG_IEEE80211R_AP */
#ifdef CONFIG_IEEE80211W
if (sm->mgmt_frame_prot && event == WPA_AUTH)
remove_ptk = 0;
#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_FILS
+ if (wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
+ (event == WPA_AUTH || event == WPA_ASSOC))
+ remove_ptk = 0;
+#endif /* CONFIG_FILS */
if (remove_ptk) {
sm->PTK_valid = FALSE;
@@ -1804,7 +1870,9 @@ SM_STATE(WPA_PTK, INITIALIZE)
wpa_remove_ptk(sm);
wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, 0);
sm->TimeoutCtr = 0;
- if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) {
+ if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
+ sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP ||
+ sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE) {
wpa_auth_set_eapol(sm->wpa_auth, sm->addr,
WPA_EAPOL_authorized, 0);
}
@@ -1813,9 +1881,14 @@ SM_STATE(WPA_PTK, INITIALIZE)
SM_STATE(WPA_PTK, DISCONNECT)
{
+ u16 reason = sm->disconnect_reason;
+
SM_ENTRY_MA(WPA_PTK, DISCONNECT, wpa_ptk);
sm->Disconnect = FALSE;
- wpa_sta_disconnect(sm->wpa_auth, sm->addr);
+ sm->disconnect_reason = 0;
+ if (!reason)
+ reason = WLAN_REASON_PREV_AUTH_NOT_VALID;
+ wpa_sta_disconnect(sm->wpa_auth, sm->addr, reason);
}
@@ -1924,17 +1997,25 @@ SM_STATE(WPA_PTK, INITPMK)
size_t len = 2 * PMK_LEN;
SM_ENTRY_MA(WPA_PTK, INITPMK, wpa_ptk);
-#ifdef CONFIG_IEEE80211R
+#ifdef CONFIG_IEEE80211R_AP
sm->xxkey_len = 0;
-#endif /* CONFIG_IEEE80211R */
+#endif /* CONFIG_IEEE80211R_AP */
if (sm->pmksa) {
wpa_printf(MSG_DEBUG, "WPA: PMK from PMKSA cache");
os_memcpy(sm->PMK, sm->pmksa->pmk, sm->pmksa->pmk_len);
sm->pmk_len = sm->pmksa->pmk_len;
+#ifdef CONFIG_DPP
+ } else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: No PMKSA cache entry for STA - reject connection");
+ sm->Disconnect = TRUE;
+ sm->disconnect_reason = WLAN_REASON_INVALID_PMKID;
+ return;
+#endif /* CONFIG_DPP */
} else if (wpa_auth_get_msk(sm->wpa_auth, sm->addr, msk, &len) == 0) {
unsigned int pmk_len;
- if (sm->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
+ if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt))
pmk_len = PMK_LEN_SUITE_B_192;
else
pmk_len = PMK_LEN;
@@ -1950,15 +2031,20 @@ SM_STATE(WPA_PTK, INITPMK)
}
os_memcpy(sm->PMK, msk, pmk_len);
sm->pmk_len = pmk_len;
-#ifdef CONFIG_IEEE80211R
+#ifdef CONFIG_IEEE80211R_AP
if (len >= 2 * PMK_LEN) {
- os_memcpy(sm->xxkey, msk + PMK_LEN, PMK_LEN);
- sm->xxkey_len = PMK_LEN;
+ if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) {
+ os_memcpy(sm->xxkey, msk, SHA384_MAC_LEN);
+ sm->xxkey_len = SHA384_MAC_LEN;
+ } else {
+ os_memcpy(sm->xxkey, msk + PMK_LEN, PMK_LEN);
+ sm->xxkey_len = PMK_LEN;
+ }
}
-#endif /* CONFIG_IEEE80211R */
+#endif /* CONFIG_IEEE80211R_AP */
} else {
wpa_printf(MSG_DEBUG, "WPA: Could not get PMK, get_msk: %p",
- sm->wpa_auth->cb.get_msk);
+ sm->wpa_auth->cb->get_msk);
sm->Disconnect = TRUE;
return;
}
@@ -1980,16 +2066,30 @@ SM_STATE(WPA_PTK, INITPMK)
SM_STATE(WPA_PTK, INITPSK)
{
const u8 *psk;
+ size_t psk_len;
+
SM_ENTRY_MA(WPA_PTK, INITPSK, wpa_ptk);
- psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, NULL);
+ psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, NULL,
+ &psk_len, NULL);
if (psk) {
- os_memcpy(sm->PMK, psk, PMK_LEN);
- sm->pmk_len = PMK_LEN;
-#ifdef CONFIG_IEEE80211R
+ os_memcpy(sm->PMK, psk, psk_len);
+ sm->pmk_len = psk_len;
+#ifdef CONFIG_IEEE80211R_AP
os_memcpy(sm->xxkey, psk, PMK_LEN);
sm->xxkey_len = PMK_LEN;
-#endif /* CONFIG_IEEE80211R */
+#endif /* CONFIG_IEEE80211R_AP */
}
+#ifdef CONFIG_SAE
+ if (wpa_auth_uses_sae(sm) && sm->pmksa) {
+ wpa_printf(MSG_DEBUG, "SAE: PMK from PMKSA cache");
+ os_memcpy(sm->PMK, sm->pmksa->pmk, sm->pmksa->pmk_len);
+ sm->pmk_len = sm->pmksa->pmk_len;
+#ifdef CONFIG_IEEE80211R_AP
+ os_memcpy(sm->xxkey, sm->pmksa->pmk, sm->pmksa->pmk_len);
+ sm->xxkey_len = sm->pmksa->pmk_len;
+#endif /* CONFIG_IEEE80211R_AP */
+ }
+#endif /* CONFIG_SAE */
sm->req_replay_counter_used = 0;
}
@@ -2005,7 +2105,7 @@ SM_STATE(WPA_PTK, PTKSTART)
sm->alt_snonce_valid = FALSE;
sm->TimeoutCtr++;
- if (sm->TimeoutCtr > (int) dot11RSNAConfigPairwiseUpdateCount) {
+ if (sm->TimeoutCtr > sm->wpa_auth->conf.wpa_pairwise_update_count) {
/* No point in sending the EAPOL-Key - we will disconnect
* immediately following this. */
return;
@@ -2014,11 +2114,23 @@ SM_STATE(WPA_PTK, PTKSTART)
wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
"sending 1/4 msg of 4-Way Handshake");
/*
- * TODO: Could add PMKID even with WPA2-PSK, but only if there is only
- * one possible PSK for this STA.
+ * For infrastructure BSS cases, it is better for the AP not to include
+ * the PMKID KDE in EAPOL-Key msg 1/4 since it could be used to initiate
+ * offline search for the passphrase/PSK without having to be able to
+ * capture a 4-way handshake from a STA that has access to the network.
+ *
+ * For IBSS cases, addition of PMKID KDE could be considered even with
+ * WPA2-PSK cases that use multiple PSKs, but only if there is a single
+ * possible PSK for this STA. However, this should not be done unless
+ * there is support for using that information on the supplicant side.
+ * The concern about exposing PMKID unnecessarily in infrastructure BSS
+ * cases would also apply here, but at least in the IBSS case, this
+ * would cover a potential real use case.
*/
if (sm->wpa == WPA_VERSION_WPA2 &&
- wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) &&
+ (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) ||
+ (sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE && sm->pmksa) ||
+ wpa_key_mgmt_sae(sm->wpa_key_mgmt)) &&
sm->wpa_key_mgmt != WPA_KEY_MGMT_OSEN) {
pmkid = buf;
pmkid_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN;
@@ -2026,11 +2138,54 @@ SM_STATE(WPA_PTK, PTKSTART)
pmkid[1] = RSN_SELECTOR_LEN + PMKID_LEN;
RSN_SELECTOR_PUT(&pmkid[2], RSN_KEY_DATA_PMKID);
if (sm->pmksa) {
+ wpa_hexdump(MSG_DEBUG,
+ "RSN: Message 1/4 PMKID from PMKSA entry",
+ sm->pmksa->pmkid, PMKID_LEN);
os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
sm->pmksa->pmkid, PMKID_LEN);
} else if (wpa_key_mgmt_suite_b(sm->wpa_key_mgmt)) {
/* No KCK available to derive PMKID */
+ wpa_printf(MSG_DEBUG,
+ "RSN: No KCK available to derive PMKID for message 1/4");
+ pmkid = NULL;
+#ifdef CONFIG_FILS
+ } else if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
+ if (sm->pmkid_set) {
+ wpa_hexdump(MSG_DEBUG,
+ "RSN: Message 1/4 PMKID from FILS/ERP",
+ sm->pmkid, PMKID_LEN);
+ os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
+ sm->pmkid, PMKID_LEN);
+ } else {
+ /* No PMKID available */
+ wpa_printf(MSG_DEBUG,
+ "RSN: No FILS/ERP PMKID available for message 1/4");
+ pmkid = NULL;
+ }
+#endif /* CONFIG_FILS */
+#ifdef CONFIG_IEEE80211R_AP
+ } else if (wpa_key_mgmt_ft(sm->wpa_key_mgmt) &&
+ sm->ft_completed) {
+ wpa_printf(MSG_DEBUG,
+ "FT: No PMKID in message 1/4 when using FT protocol");
pmkid = NULL;
+ pmkid_len = 0;
+#endif /* CONFIG_IEEE80211R_AP */
+#ifdef CONFIG_SAE
+ } else if (wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
+ if (sm->pmkid_set) {
+ wpa_hexdump(MSG_DEBUG,
+ "RSN: Message 1/4 PMKID from SAE",
+ sm->pmkid, PMKID_LEN);
+ os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
+ sm->pmkid, PMKID_LEN);
+ } else {
+ /* No PMKID available */
+ wpa_printf(MSG_DEBUG,
+ "RSN: No SAE PMKID available for message 1/4");
+ pmkid = NULL;
+ }
+#endif /* CONFIG_SAE */
} else {
/*
* Calculate PMKID since no PMKSA cache entry was
@@ -2038,7 +2193,10 @@ SM_STATE(WPA_PTK, PTKSTART)
*/
rsn_pmkid(sm->PMK, sm->pmk_len, sm->wpa_auth->addr,
sm->addr, &pmkid[2 + RSN_SELECTOR_LEN],
- wpa_key_mgmt_sha256(sm->wpa_key_mgmt));
+ sm->wpa_key_mgmt);
+ wpa_hexdump(MSG_DEBUG,
+ "RSN: Message 1/4 PMKID derived from PMK",
+ &pmkid[2 + RSN_SELECTOR_LEN], PMKID_LEN);
}
}
wpa_send_eapol(sm->wpa_auth, sm,
@@ -2051,54 +2209,678 @@ static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
const u8 *pmk, unsigned int pmk_len,
struct wpa_ptk *ptk)
{
-#ifdef CONFIG_IEEE80211R
- if (wpa_key_mgmt_ft(sm->wpa_key_mgmt))
- return wpa_auth_derive_ptk_ft(sm, pmk, ptk);
-#endif /* CONFIG_IEEE80211R */
+ const u8 *z = NULL;
+ size_t z_len = 0;
+
+#ifdef CONFIG_IEEE80211R_AP
+ if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
+ if (sm->ft_completed) {
+ u8 ptk_name[WPA_PMK_NAME_LEN];
+
+ return wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len,
+ sm->SNonce, sm->ANonce,
+ sm->addr, sm->wpa_auth->addr,
+ sm->pmk_r1_name,
+ ptk, ptk_name,
+ sm->wpa_key_mgmt,
+ sm->pairwise);
+ }
+ return wpa_auth_derive_ptk_ft(sm, ptk);
+ }
+#endif /* CONFIG_IEEE80211R_AP */
+
+#ifdef CONFIG_DPP2
+ if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && sm->dpp_z) {
+ z = wpabuf_head(sm->dpp_z);
+ z_len = wpabuf_len(sm->dpp_z);
+ }
+#endif /* CONFIG_DPP2 */
return wpa_pmk_to_ptk(pmk, pmk_len, "Pairwise key expansion",
sm->wpa_auth->addr, sm->addr, sm->ANonce, snonce,
- ptk, sm->wpa_key_mgmt, sm->pairwise);
+ ptk, sm->wpa_key_mgmt, sm->pairwise, z, z_len);
+}
+
+
+#ifdef CONFIG_FILS
+
+int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk,
+ size_t pmk_len, const u8 *snonce, const u8 *anonce,
+ const u8 *dhss, size_t dhss_len,
+ struct wpabuf *g_sta, struct wpabuf *g_ap)
+{
+ u8 ick[FILS_ICK_MAX_LEN];
+ size_t ick_len;
+ int res;
+ u8 fils_ft[FILS_FT_MAX_LEN];
+ size_t fils_ft_len = 0;
+
+ res = fils_pmk_to_ptk(pmk, pmk_len, sm->addr, sm->wpa_auth->addr,
+ snonce, anonce, dhss, dhss_len,
+ &sm->PTK, ick, &ick_len,
+ sm->wpa_key_mgmt, sm->pairwise,
+ fils_ft, &fils_ft_len);
+ if (res < 0)
+ return res;
+ sm->PTK_valid = TRUE;
+ sm->tk_already_set = FALSE;
+
+#ifdef CONFIG_IEEE80211R_AP
+ if (fils_ft_len) {
+ struct wpa_authenticator *wpa_auth = sm->wpa_auth;
+ struct wpa_auth_config *conf = &wpa_auth->conf;
+ u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN];
+ int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
+ size_t pmk_r0_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN;
+
+ if (wpa_derive_pmk_r0(fils_ft, fils_ft_len,
+ conf->ssid, conf->ssid_len,
+ conf->mobility_domain,
+ conf->r0_key_holder,
+ conf->r0_key_holder_len,
+ sm->addr, pmk_r0, pmk_r0_name,
+ use_sha384) < 0)
+ return -1;
+
+ wpa_hexdump_key(MSG_DEBUG, "FILS+FT: PMK-R0",
+ pmk_r0, pmk_r0_len);
+ wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR0Name",
+ pmk_r0_name, WPA_PMK_NAME_LEN);
+ wpa_ft_store_pmk_fils(sm, pmk_r0, pmk_r0_name);
+ os_memset(fils_ft, 0, sizeof(fils_ft));
+
+ res = wpa_derive_pmk_r1_name(pmk_r0_name, conf->r1_key_holder,
+ sm->addr, sm->pmk_r1_name,
+ use_sha384);
+ os_memset(pmk_r0, 0, PMK_LEN_MAX);
+ if (res < 0)
+ return -1;
+ wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR1Name", sm->pmk_r1_name,
+ WPA_PMK_NAME_LEN);
+ sm->pmk_r1_name_valid = 1;
+ }
+#endif /* CONFIG_IEEE80211R_AP */
+
+ res = fils_key_auth_sk(ick, ick_len, snonce, anonce,
+ sm->addr, sm->wpa_auth->addr,
+ g_sta ? wpabuf_head(g_sta) : NULL,
+ g_sta ? wpabuf_len(g_sta) : 0,
+ g_ap ? wpabuf_head(g_ap) : NULL,
+ g_ap ? wpabuf_len(g_ap) : 0,
+ sm->wpa_key_mgmt, sm->fils_key_auth_sta,
+ sm->fils_key_auth_ap,
+ &sm->fils_key_auth_len);
+ os_memset(ick, 0, sizeof(ick));
+
+ /* Store nonces for (Re)Association Request/Response frame processing */
+ os_memcpy(sm->SNonce, snonce, FILS_NONCE_LEN);
+ os_memcpy(sm->ANonce, anonce, FILS_NONCE_LEN);
+
+ return res;
+}
+
+
+static int wpa_aead_decrypt(struct wpa_state_machine *sm, struct wpa_ptk *ptk,
+ u8 *buf, size_t buf_len, u16 *_key_data_len)
+{
+ struct ieee802_1x_hdr *hdr;
+ struct wpa_eapol_key *key;
+ u8 *pos;
+ u16 key_data_len;
+ u8 *tmp;
+ const u8 *aad[1];
+ size_t aad_len[1];
+
+ hdr = (struct ieee802_1x_hdr *) buf;
+ key = (struct wpa_eapol_key *) (hdr + 1);
+ pos = (u8 *) (key + 1);
+ key_data_len = WPA_GET_BE16(pos);
+ if (key_data_len < AES_BLOCK_SIZE ||
+ key_data_len > buf_len - sizeof(*hdr) - sizeof(*key) - 2) {
+ wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO,
+ "No room for AES-SIV data in the frame");
+ return -1;
+ }
+ pos += 2; /* Pointing at the Encrypted Key Data field */
+
+ tmp = os_malloc(key_data_len);
+ if (!tmp)
+ return -1;
+
+ /* AES-SIV AAD from EAPOL protocol version field (inclusive) to
+ * to Key Data (exclusive). */
+ aad[0] = buf;
+ aad_len[0] = pos - buf;
+ if (aes_siv_decrypt(ptk->kek, ptk->kek_len, pos, key_data_len,
+ 1, aad, aad_len, tmp) < 0) {
+ wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO,
+ "Invalid AES-SIV data in the frame");
+ bin_clear_free(tmp, key_data_len);
+ return -1;
+ }
+
+ /* AEAD decryption and validation completed successfully */
+ key_data_len -= AES_BLOCK_SIZE;
+ wpa_hexdump_key(MSG_DEBUG, "WPA: Decrypted Key Data",
+ tmp, key_data_len);
+
+ /* Replace Key Data field with the decrypted version */
+ os_memcpy(pos, tmp, key_data_len);
+ pos -= 2; /* Key Data Length field */
+ WPA_PUT_BE16(pos, key_data_len);
+ bin_clear_free(tmp, key_data_len);
+ if (_key_data_len)
+ *_key_data_len = key_data_len;
+ return 0;
+}
+
+
+const u8 * wpa_fils_validate_fils_session(struct wpa_state_machine *sm,
+ const u8 *ies, size_t ies_len,
+ const u8 *fils_session)
+{
+ const u8 *ie, *end;
+ const u8 *session = NULL;
+
+ if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
+ wpa_printf(MSG_DEBUG,
+ "FILS: Not a FILS AKM - reject association");
+ return NULL;
+ }
+
+ /* Verify Session element */
+ ie = ies;
+ end = ((const u8 *) ie) + ies_len;
+ while (ie + 1 < end) {
+ if (ie + 2 + ie[1] > end)
+ break;
+ if (ie[0] == WLAN_EID_EXTENSION &&
+ ie[1] >= 1 + FILS_SESSION_LEN &&
+ ie[2] == WLAN_EID_EXT_FILS_SESSION) {
+ session = ie;
+ break;
+ }
+ ie += 2 + ie[1];
+ }
+
+ if (!session) {
+ wpa_printf(MSG_DEBUG,
+ "FILS: %s: Could not find FILS Session element in Assoc Req - reject",
+ __func__);
+ return NULL;
+ }
+
+ if (!fils_session) {
+ wpa_printf(MSG_DEBUG,
+ "FILS: %s: Could not find FILS Session element in STA entry - reject",
+ __func__);
+ return NULL;
+ }
+
+ if (os_memcmp(fils_session, session + 3, FILS_SESSION_LEN) != 0) {
+ wpa_printf(MSG_DEBUG, "FILS: Session mismatch");
+ wpa_hexdump(MSG_DEBUG, "FILS: Expected FILS Session",
+ fils_session, FILS_SESSION_LEN);
+ wpa_hexdump(MSG_DEBUG, "FILS: Received FILS Session",
+ session + 3, FILS_SESSION_LEN);
+ return NULL;
+ }
+ return session;
+}
+
+
+int wpa_fils_validate_key_confirm(struct wpa_state_machine *sm, const u8 *ies,
+ size_t ies_len)
+{
+ struct ieee802_11_elems elems;
+
+ if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) {
+ wpa_printf(MSG_DEBUG,
+ "FILS: Failed to parse decrypted elements");
+ return -1;
+ }
+
+ if (!elems.fils_session) {
+ wpa_printf(MSG_DEBUG, "FILS: No FILS Session element");
+ return -1;
+ }
+
+ if (!elems.fils_key_confirm) {
+ wpa_printf(MSG_DEBUG, "FILS: No FILS Key Confirm element");
+ return -1;
+ }
+
+ if (elems.fils_key_confirm_len != sm->fils_key_auth_len) {
+ wpa_printf(MSG_DEBUG,
+ "FILS: Unexpected Key-Auth length %d (expected %d)",
+ elems.fils_key_confirm_len,
+ (int) sm->fils_key_auth_len);
+ return -1;
+ }
+
+ if (os_memcmp(elems.fils_key_confirm, sm->fils_key_auth_sta,
+ sm->fils_key_auth_len) != 0) {
+ wpa_printf(MSG_DEBUG, "FILS: Key-Auth mismatch");
+ wpa_hexdump(MSG_DEBUG, "FILS: Received Key-Auth",
+ elems.fils_key_confirm, elems.fils_key_confirm_len);
+ wpa_hexdump(MSG_DEBUG, "FILS: Expected Key-Auth",
+ sm->fils_key_auth_sta, sm->fils_key_auth_len);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int fils_decrypt_assoc(struct wpa_state_machine *sm, const u8 *fils_session,
+ const struct ieee80211_mgmt *mgmt, size_t frame_len,
+ u8 *pos, size_t left)
+{
+ u16 fc, stype;
+ const u8 *end, *ie_start, *ie, *session, *crypt;
+ const u8 *aad[5];
+ size_t aad_len[5];
+
+ if (!sm || !sm->PTK_valid) {
+ wpa_printf(MSG_DEBUG,
+ "FILS: No KEK to decrypt Assocication Request frame");
+ return -1;
+ }
+
+ if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
+ wpa_printf(MSG_DEBUG,
+ "FILS: Not a FILS AKM - reject association");
+ return -1;
+ }
+
+ end = ((const u8 *) mgmt) + frame_len;
+ fc = le_to_host16(mgmt->frame_control);
+ stype = WLAN_FC_GET_STYPE(fc);
+ if (stype == WLAN_FC_STYPE_REASSOC_REQ)
+ ie_start = mgmt->u.reassoc_req.variable;
+ else
+ ie_start = mgmt->u.assoc_req.variable;
+ ie = ie_start;
+
+ /*
+ * Find FILS Session element which is the last unencrypted element in
+ * the frame.
+ */
+ session = wpa_fils_validate_fils_session(sm, ie, end - ie,
+ fils_session);
+ if (!session) {
+ wpa_printf(MSG_DEBUG, "FILS: Session validation failed");
+ return -1;
+ }
+
+ crypt = session + 2 + session[1];
+
+ if (end - crypt < AES_BLOCK_SIZE) {
+ wpa_printf(MSG_DEBUG,
+ "FILS: Too short frame to include AES-SIV data");
+ return -1;
+ }
+
+ /* AES-SIV AAD vectors */
+
+ /* The STA's MAC address */
+ aad[0] = mgmt->sa;
+ aad_len[0] = ETH_ALEN;
+ /* The AP's BSSID */
+ aad[1] = mgmt->da;
+ aad_len[1] = ETH_ALEN;
+ /* The STA's nonce */
+ aad[2] = sm->SNonce;
+ aad_len[2] = FILS_NONCE_LEN;
+ /* The AP's nonce */
+ aad[3] = sm->ANonce;
+ aad_len[3] = FILS_NONCE_LEN;
+ /*
+ * The (Re)Association Request frame from the Capability Information
+ * field to the FILS Session element (both inclusive).
+ */
+ aad[4] = (const u8 *) &mgmt->u.assoc_req.capab_info;
+ aad_len[4] = crypt - aad[4];
+
+ if (aes_siv_decrypt(sm->PTK.kek, sm->PTK.kek_len, crypt, end - crypt,
+ 5, aad, aad_len, pos + (crypt - ie_start)) < 0) {
+ wpa_printf(MSG_DEBUG,
+ "FILS: Invalid AES-SIV data in the frame");
+ return -1;
+ }
+ wpa_hexdump(MSG_DEBUG, "FILS: Decrypted Association Request elements",
+ pos, left - AES_BLOCK_SIZE);
+
+ if (wpa_fils_validate_key_confirm(sm, pos, left - AES_BLOCK_SIZE) < 0) {
+ wpa_printf(MSG_DEBUG, "FILS: Key Confirm validation failed");
+ return -1;
+ }
+
+ return left - AES_BLOCK_SIZE;
+}
+
+
+int fils_encrypt_assoc(struct wpa_state_machine *sm, u8 *buf,
+ size_t current_len, size_t max_len,
+ const struct wpabuf *hlp)
+{
+ u8 *end = buf + max_len;
+ u8 *pos = buf + current_len;
+ struct ieee80211_mgmt *mgmt;
+ struct wpabuf *plain;
+ const u8 *aad[5];
+ size_t aad_len[5];
+
+ if (!sm || !sm->PTK_valid)
+ return -1;
+
+ wpa_hexdump(MSG_DEBUG,
+ "FILS: Association Response frame before FILS processing",
+ buf, current_len);
+
+ mgmt = (struct ieee80211_mgmt *) buf;
+
+ /* AES-SIV AAD vectors */
+
+ /* The AP's BSSID */
+ aad[0] = mgmt->sa;
+ aad_len[0] = ETH_ALEN;
+ /* The STA's MAC address */
+ aad[1] = mgmt->da;
+ aad_len[1] = ETH_ALEN;
+ /* The AP's nonce */
+ aad[2] = sm->ANonce;
+ aad_len[2] = FILS_NONCE_LEN;
+ /* The STA's nonce */
+ aad[3] = sm->SNonce;
+ aad_len[3] = FILS_NONCE_LEN;
+ /*
+ * The (Re)Association Response frame from the Capability Information
+ * field (the same offset in both Association and Reassociation
+ * Response frames) to the FILS Session element (both inclusive).
+ */
+ aad[4] = (const u8 *) &mgmt->u.assoc_resp.capab_info;
+ aad_len[4] = pos - aad[4];
+
+ /* The following elements will be encrypted with AES-SIV */
+ plain = fils_prepare_plainbuf(sm, hlp);
+ if (!plain) {
+ wpa_printf(MSG_DEBUG, "FILS: Plain buffer prep failed");
+ return -1;
+ }
+
+ if (pos + wpabuf_len(plain) + AES_BLOCK_SIZE > end) {
+ wpa_printf(MSG_DEBUG,
+ "FILS: Not enough room for FILS elements");
+ wpabuf_free(plain);
+ return -1;
+ }
+
+ wpa_hexdump_buf_key(MSG_DEBUG, "FILS: Association Response plaintext",
+ plain);
+
+ if (aes_siv_encrypt(sm->PTK.kek, sm->PTK.kek_len,
+ wpabuf_head(plain), wpabuf_len(plain),
+ 5, aad, aad_len, pos) < 0) {
+ wpabuf_free(plain);
+ return -1;
+ }
+
+ wpa_hexdump(MSG_DEBUG,
+ "FILS: Encrypted Association Response elements",
+ pos, AES_BLOCK_SIZE + wpabuf_len(plain));
+ current_len += wpabuf_len(plain) + AES_BLOCK_SIZE;
+ wpabuf_free(plain);
+
+ sm->fils_completed = 1;
+
+ return current_len;
+}
+
+
+static struct wpabuf * fils_prepare_plainbuf(struct wpa_state_machine *sm,
+ const struct wpabuf *hlp)
+{
+ struct wpabuf *plain;
+ u8 *len, *tmp, *tmp2;
+ u8 hdr[2];
+ u8 *gtk, dummy_gtk[32];
+ size_t gtk_len;
+ struct wpa_group *gsm;
+
+ plain = wpabuf_alloc(1000);
+ if (!plain)
+ return NULL;
+
+ /* TODO: FILS Public Key */
+
+ /* FILS Key Confirmation */
+ wpabuf_put_u8(plain, WLAN_EID_EXTENSION); /* Element ID */
+ wpabuf_put_u8(plain, 1 + sm->fils_key_auth_len); /* Length */
+ /* Element ID Extension */
+ wpabuf_put_u8(plain, WLAN_EID_EXT_FILS_KEY_CONFIRM);
+ wpabuf_put_data(plain, sm->fils_key_auth_ap, sm->fils_key_auth_len);
+
+ /* FILS HLP Container */
+ if (hlp)
+ wpabuf_put_buf(plain, hlp);
+
+ /* TODO: FILS IP Address Assignment */
+
+ /* Key Delivery */
+ gsm = sm->group;
+ wpabuf_put_u8(plain, WLAN_EID_EXTENSION); /* Element ID */
+ len = wpabuf_put(plain, 1);
+ wpabuf_put_u8(plain, WLAN_EID_EXT_KEY_DELIVERY);
+ wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN,
+ wpabuf_put(plain, WPA_KEY_RSC_LEN));
+ /* GTK KDE */
+ gtk = gsm->GTK[gsm->GN - 1];
+ gtk_len = gsm->GTK_len;
+ if (sm->wpa_auth->conf.disable_gtk ||
+ sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
+ /*
+ * Provide unique random GTK to each STA to prevent use
+ * of GTK in the BSS.
+ */
+ if (random_get_bytes(dummy_gtk, gtk_len) < 0) {
+ wpabuf_free(plain);
+ return NULL;
+ }
+ gtk = dummy_gtk;
+ }
+ hdr[0] = gsm->GN & 0x03;
+ hdr[1] = 0;
+ tmp = wpabuf_put(plain, 0);
+ tmp2 = wpa_add_kde(tmp, RSN_KEY_DATA_GROUPKEY, hdr, 2,
+ gtk, gtk_len);
+ wpabuf_put(plain, tmp2 - tmp);
+
+ /* IGTK KDE */
+ tmp = wpabuf_put(plain, 0);
+ tmp2 = ieee80211w_kde_add(sm, tmp);
+ wpabuf_put(plain, tmp2 - tmp);
+
+ *len = (u8 *) wpabuf_put(plain, 0) - len - 1;
+
+#ifdef CONFIG_OCV
+ if (wpa_auth_uses_ocv(sm)) {
+ struct wpa_channel_info ci;
+ u8 *pos;
+
+ if (wpa_channel_info(sm->wpa_auth, &ci) != 0) {
+ wpa_printf(MSG_WARNING,
+ "FILS: Failed to get channel info for OCI element");
+ wpabuf_free(plain);
+ return NULL;
+ }
+
+ pos = wpabuf_put(plain, OCV_OCI_EXTENDED_LEN);
+ if (ocv_insert_extended_oci(&ci, pos) < 0) {
+ wpabuf_free(plain);
+ return NULL;
+ }
+ }
+#endif /* CONFIG_OCV */
+
+ return plain;
}
+int fils_set_tk(struct wpa_state_machine *sm)
+{
+ enum wpa_alg alg;
+ int klen;
+
+ if (!sm || !sm->PTK_valid) {
+ wpa_printf(MSG_DEBUG, "FILS: No valid PTK available to set TK");
+ return -1;
+ }
+ if (sm->tk_already_set) {
+ wpa_printf(MSG_DEBUG, "FILS: TK already set to the driver");
+ return -1;
+ }
+
+ alg = wpa_cipher_to_alg(sm->pairwise);
+ klen = wpa_cipher_key_len(sm->pairwise);
+
+ wpa_printf(MSG_DEBUG, "FILS: Configure TK to the driver");
+ if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0,
+ sm->PTK.tk, klen)) {
+ wpa_printf(MSG_DEBUG, "FILS: Failed to set TK to the driver");
+ return -1;
+ }
+ sm->tk_already_set = TRUE;
+
+ return 0;
+}
+
+
+u8 * hostapd_eid_assoc_fils_session(struct wpa_state_machine *sm, u8 *buf,
+ const u8 *fils_session, struct wpabuf *hlp)
+{
+ struct wpabuf *plain;
+ u8 *pos = buf;
+
+ /* FILS Session */
+ *pos++ = WLAN_EID_EXTENSION; /* Element ID */
+ *pos++ = 1 + FILS_SESSION_LEN; /* Length */
+ *pos++ = WLAN_EID_EXT_FILS_SESSION; /* Element ID Extension */
+ os_memcpy(pos, fils_session, FILS_SESSION_LEN);
+ pos += FILS_SESSION_LEN;
+
+ plain = fils_prepare_plainbuf(sm, hlp);
+ if (!plain) {
+ wpa_printf(MSG_DEBUG, "FILS: Plain buffer prep failed");
+ return NULL;
+ }
+
+ os_memcpy(pos, wpabuf_head(plain), wpabuf_len(plain));
+ pos += wpabuf_len(plain);
+
+ wpa_printf(MSG_DEBUG, "%s: plain buf_len: %u", __func__,
+ (unsigned int) wpabuf_len(plain));
+ wpabuf_free(plain);
+ sm->fils_completed = 1;
+ return pos;
+}
+
+#endif /* CONFIG_FILS */
+
+
+#ifdef CONFIG_OCV
+int get_sta_tx_parameters(struct wpa_state_machine *sm, int ap_max_chanwidth,
+ int ap_seg1_idx, int *bandwidth, int *seg1_idx)
+{
+ struct wpa_authenticator *wpa_auth = sm->wpa_auth;
+
+ if (!wpa_auth->cb->get_sta_tx_params)
+ return -1;
+ return wpa_auth->cb->get_sta_tx_params(wpa_auth->cb_ctx, sm->addr,
+ ap_max_chanwidth, ap_seg1_idx,
+ bandwidth, seg1_idx);
+}
+#endif /* CONFIG_OCV */
+
+
SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
{
+ struct wpa_authenticator *wpa_auth = sm->wpa_auth;
struct wpa_ptk PTK;
int ok = 0, psk_found = 0;
const u8 *pmk = NULL;
- unsigned int pmk_len;
+ size_t pmk_len;
+ int ft;
+ const u8 *eapol_key_ie, *key_data, *mic;
+ u16 key_data_length;
+ size_t mic_len, eapol_key_ie_len;
+ struct ieee802_1x_hdr *hdr;
+ struct wpa_eapol_key *key;
+ struct wpa_eapol_ie_parse kde;
+ int vlan_id = 0;
SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk);
sm->EAPOLKeyReceived = FALSE;
sm->update_snonce = FALSE;
+ os_memset(&PTK, 0, sizeof(PTK));
+
+ mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
/* WPA with IEEE 802.1X: use the derived PMK from EAP
* WPA-PSK: iterate through possible PSKs and select the one matching
* the packet */
for (;;) {
- if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) {
+ if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
+ !wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr,
- sm->p2p_dev_addr, pmk);
+ sm->p2p_dev_addr, pmk, &pmk_len,
+ &vlan_id);
if (pmk == NULL)
break;
psk_found = 1;
- pmk_len = PMK_LEN;
+#ifdef CONFIG_IEEE80211R_AP
+ if (wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) {
+ os_memcpy(sm->xxkey, pmk, pmk_len);
+ sm->xxkey_len = pmk_len;
+ }
+#endif /* CONFIG_IEEE80211R_AP */
} else {
pmk = sm->PMK;
pmk_len = sm->pmk_len;
}
- wpa_derive_ptk(sm, sm->SNonce, pmk, pmk_len, &PTK);
+ if ((!pmk || !pmk_len) && sm->pmksa) {
+ wpa_printf(MSG_DEBUG, "WPA: Use PMK from PMKSA cache");
+ pmk = sm->pmksa->pmk;
+ pmk_len = sm->pmksa->pmk_len;
+ }
- if (wpa_verify_key_mic(sm->wpa_key_mgmt, &PTK,
+ if (wpa_derive_ptk(sm, sm->SNonce, pmk, pmk_len, &PTK) < 0)
+ break;
+
+ if (mic_len &&
+ wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK,
sm->last_rx_eapol_key,
sm->last_rx_eapol_key_len) == 0) {
+ if (sm->PMK != pmk) {
+ os_memcpy(sm->PMK, pmk, pmk_len);
+ sm->pmk_len = pmk_len;
+ }
+ ok = 1;
+ break;
+ }
+
+#ifdef CONFIG_FILS
+ if (!mic_len &&
+ wpa_aead_decrypt(sm, &PTK, sm->last_rx_eapol_key,
+ sm->last_rx_eapol_key_len, NULL) == 0) {
ok = 1;
break;
}
+#endif /* CONFIG_FILS */
- if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt))
+ if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
+ wpa_key_mgmt_sae(sm->wpa_key_mgmt))
break;
}
@@ -2110,7 +2892,105 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
return;
}
-#ifdef CONFIG_IEEE80211R
+ /*
+ * Note: last_rx_eapol_key length fields have already been validated in
+ * wpa_receive().
+ */
+ hdr = (struct ieee802_1x_hdr *) sm->last_rx_eapol_key;
+ key = (struct wpa_eapol_key *) (hdr + 1);
+ mic = (u8 *) (key + 1);
+ key_data = mic + mic_len + 2;
+ key_data_length = WPA_GET_BE16(mic + mic_len);
+ if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) -
+ sizeof(*key) - mic_len - 2)
+ return;
+
+ if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) {
+ wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
+ "received EAPOL-Key msg 2/4 with invalid Key Data contents");
+ return;
+ }
+ if (kde.rsn_ie) {
+ eapol_key_ie = kde.rsn_ie;
+ eapol_key_ie_len = kde.rsn_ie_len;
+ } else if (kde.osen) {
+ eapol_key_ie = kde.osen;
+ eapol_key_ie_len = kde.osen_len;
+ } else {
+ eapol_key_ie = kde.wpa_ie;
+ eapol_key_ie_len = kde.wpa_ie_len;
+ }
+ ft = sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt);
+ if (sm->wpa_ie == NULL ||
+ wpa_compare_rsn_ie(ft, sm->wpa_ie, sm->wpa_ie_len,
+ eapol_key_ie, eapol_key_ie_len)) {
+ wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ "WPA IE from (Re)AssocReq did not match with msg 2/4");
+ if (sm->wpa_ie) {
+ wpa_hexdump(MSG_DEBUG, "WPA IE in AssocReq",
+ sm->wpa_ie, sm->wpa_ie_len);
+ }
+ wpa_hexdump(MSG_DEBUG, "WPA IE in msg 2/4",
+ eapol_key_ie, eapol_key_ie_len);
+ /* MLME-DEAUTHENTICATE.request */
+ wpa_sta_disconnect(wpa_auth, sm->addr,
+ WLAN_REASON_PREV_AUTH_NOT_VALID);
+ return;
+ }
+#ifdef CONFIG_OCV
+ if (wpa_auth_uses_ocv(sm)) {
+ struct wpa_channel_info ci;
+ int tx_chanwidth;
+ int tx_seg1_idx;
+
+ if (wpa_channel_info(wpa_auth, &ci) != 0) {
+ wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ "Failed to get channel info to validate received OCI in EAPOL-Key 2/4");
+ return;
+ }
+
+ if (get_sta_tx_parameters(sm,
+ channel_width_to_int(ci.chanwidth),
+ ci.seg1_idx, &tx_chanwidth,
+ &tx_seg1_idx) < 0)
+ return;
+
+ if (ocv_verify_tx_params(kde.oci, kde.oci_len, &ci,
+ tx_chanwidth, tx_seg1_idx) != 0) {
+ wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ ocv_errorstr);
+ return;
+ }
+ }
+#endif /* CONFIG_OCV */
+#ifdef CONFIG_IEEE80211R_AP
+ if (ft && ft_check_msg_2_of_4(wpa_auth, sm, &kde) < 0) {
+ wpa_sta_disconnect(wpa_auth, sm->addr,
+ WLAN_REASON_PREV_AUTH_NOT_VALID);
+ return;
+ }
+#endif /* CONFIG_IEEE80211R_AP */
+#ifdef CONFIG_P2P
+ if (kde.ip_addr_req && kde.ip_addr_req[0] &&
+ wpa_auth->ip_pool && WPA_GET_BE32(sm->ip_addr) == 0) {
+ int idx;
+ wpa_printf(MSG_DEBUG,
+ "P2P: IP address requested in EAPOL-Key exchange");
+ idx = bitfield_get_first_zero(wpa_auth->ip_pool);
+ if (idx >= 0) {
+ u32 start = WPA_GET_BE32(wpa_auth->conf.ip_addr_start);
+ bitfield_set(wpa_auth->ip_pool, idx);
+ WPA_PUT_BE32(sm->ip_addr, start + idx);
+ wpa_printf(MSG_DEBUG,
+ "P2P: Assigned IP address %u.%u.%u.%u to "
+ MACSTR, sm->ip_addr[0], sm->ip_addr[1],
+ sm->ip_addr[2], sm->ip_addr[3],
+ MAC2STR(sm->addr));
+ }
+ }
+#endif /* CONFIG_P2P */
+
+#ifdef CONFIG_IEEE80211R_AP
if (sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
/*
* Verify that PMKR1Name from EAPOL-Key message 2/4 matches
@@ -2129,7 +3009,14 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
return;
}
}
-#endif /* CONFIG_IEEE80211R */
+#endif /* CONFIG_IEEE80211R_AP */
+
+ if (vlan_id && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
+ wpa_auth_update_vlan(wpa_auth, sm->addr, vlan_id) < 0) {
+ wpa_sta_disconnect(wpa_auth, sm->addr,
+ WLAN_REASON_PREV_AUTH_NOT_VALID);
+ return;
+ }
sm->pending_1_of_4_timeout = 0;
eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm);
@@ -2188,7 +3075,8 @@ static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos)
else
os_memcpy(igtk.pn, rsc, sizeof(igtk.pn));
os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], len);
- if (sm->wpa_auth->conf.disable_gtk) {
+ if (sm->wpa_auth->conf.disable_gtk ||
+ sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
/*
* Provide unique random IGTK to each STA to prevent use of
* IGTK in the BSS.
@@ -2219,6 +3107,36 @@ static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos)
#endif /* CONFIG_IEEE80211W */
+static int ocv_oci_len(struct wpa_state_machine *sm)
+{
+#ifdef CONFIG_OCV
+ if (wpa_auth_uses_ocv(sm))
+ return OCV_OCI_KDE_LEN;
+#endif /* CONFIG_OCV */
+ return 0;
+}
+
+static int ocv_oci_add(struct wpa_state_machine *sm, u8 **argpos)
+{
+#ifdef CONFIG_OCV
+ struct wpa_channel_info ci;
+
+ if (!wpa_auth_uses_ocv(sm))
+ return 0;
+
+ if (wpa_channel_info(sm->wpa_auth, &ci) != 0) {
+ wpa_printf(MSG_WARNING,
+ "Failed to get channel info for OCI element");
+ return -1;
+ }
+
+ return ocv_insert_oci_kde(&ci, argpos);
+#else /* CONFIG_OCV */
+ return 0;
+#endif /* CONFIG_OCV */
+}
+
+
SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
{
u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos, dummy_gtk[32];
@@ -2231,7 +3149,12 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
sm->TimeoutEvt = FALSE;
sm->TimeoutCtr++;
- if (sm->TimeoutCtr > (int) dot11RSNAConfigPairwiseUpdateCount) {
+ if (sm->wpa_auth->conf.wpa_disable_eapol_key_retries &&
+ sm->TimeoutCtr > 1) {
+ /* Do not allow retransmission of EAPOL-Key msg 3/4 */
+ return;
+ }
+ if (sm->TimeoutCtr > sm->wpa_auth->conf.wpa_pairwise_update_count) {
/* No point in sending the EAPOL-Key - we will disconnect
* immediately following this. */
return;
@@ -2261,7 +3184,8 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
secure = 1;
gtk = gsm->GTK[gsm->GN - 1];
gtk_len = gsm->GTK_len;
- if (sm->wpa_auth->conf.disable_gtk) {
+ if (sm->wpa_auth->conf.disable_gtk ||
+ sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
/*
* Provide unique random GTK to each STA to prevent use
* of GTK in the BSS.
@@ -2296,15 +3220,15 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
}
}
- kde_len = wpa_ie_len + ieee80211w_kde_len(sm);
+ kde_len = wpa_ie_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm);
if (gtk)
kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len;
-#ifdef CONFIG_IEEE80211R
+#ifdef CONFIG_IEEE80211R_AP
if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */
kde_len += 300; /* FTIE + 2 * TIE */
}
-#endif /* CONFIG_IEEE80211R */
+#endif /* CONFIG_IEEE80211R_AP */
#ifdef CONFIG_P2P
if (WPA_GET_BE32(sm->ip_addr) > 0)
kde_len += 2 + RSN_SELECTOR_LEN + 3 * 4;
@@ -2316,7 +3240,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
pos = kde;
os_memcpy(pos, wpa_ie, wpa_ie_len);
pos += wpa_ie_len;
-#ifdef CONFIG_IEEE80211R
+#ifdef CONFIG_IEEE80211R_AP
if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
int res;
size_t elen;
@@ -2332,7 +3256,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
pos -= wpa_ie_len;
pos += elen;
}
-#endif /* CONFIG_IEEE80211R */
+#endif /* CONFIG_IEEE80211R_AP */
if (gtk) {
u8 hdr[2];
hdr[0] = keyidx & 0x03;
@@ -2341,8 +3265,12 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
gtk, gtk_len);
}
pos = ieee80211w_kde_add(sm, pos);
+ if (ocv_oci_add(sm, &pos) < 0) {
+ os_free(kde);
+ return;
+ }
-#ifdef CONFIG_IEEE80211R
+#ifdef CONFIG_IEEE80211R_AP
if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
int res;
struct wpa_auth_config *conf;
@@ -2354,7 +3282,10 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
2 + sm->assoc_resp_ftie[1]);
res = 2 + sm->assoc_resp_ftie[1];
} else {
- res = wpa_write_ftie(conf, conf->r0_key_holder,
+ int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
+
+ res = wpa_write_ftie(conf, use_sha384,
+ conf->r0_key_holder,
conf->r0_key_holder_len,
NULL, NULL, pos,
kde + kde_len - pos,
@@ -2379,10 +3310,10 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
*pos++ = WLAN_EID_TIMEOUT_INTERVAL;
*pos++ = 5;
*pos++ = WLAN_TIMEOUT_KEY_LIFETIME;
- WPA_PUT_LE32(pos, conf->r0_key_lifetime * 60);
+ WPA_PUT_LE32(pos, conf->r0_key_lifetime);
pos += 4;
}
-#endif /* CONFIG_IEEE80211R */
+#endif /* CONFIG_IEEE80211R_AP */
#ifdef CONFIG_P2P
if (WPA_GET_BE32(sm->ip_addr) > 0) {
u8 addr[3 * 4];
@@ -2395,7 +3326,9 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
#endif /* CONFIG_P2P */
wpa_send_eapol(sm->wpa_auth, sm,
- (secure ? WPA_KEY_INFO_SECURE : 0) | WPA_KEY_INFO_MIC |
+ (secure ? WPA_KEY_INFO_SECURE : 0) |
+ (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
+ WPA_KEY_INFO_MIC : 0) |
WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL |
WPA_KEY_INFO_KEY_TYPE,
_rsc, sm->ANonce, kde, pos - kde, keyidx, encr);
@@ -2412,20 +3345,18 @@ SM_STATE(WPA_PTK, PTKINITDONE)
int klen = wpa_cipher_key_len(sm->pairwise);
if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0,
sm->PTK.tk, klen)) {
- wpa_sta_disconnect(sm->wpa_auth, sm->addr);
+ wpa_sta_disconnect(sm->wpa_auth, sm->addr,
+ WLAN_REASON_PREV_AUTH_NOT_VALID);
return;
}
/* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */
sm->pairwise_set = TRUE;
- if (sm->wpa_auth->conf.wpa_ptk_rekey) {
- eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
- eloop_register_timeout(sm->wpa_auth->conf.
- wpa_ptk_rekey, 0, wpa_rekey_ptk,
- sm->wpa_auth, sm);
- }
+ wpa_auth_set_ptk_rekey_timer(sm);
- if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) {
+ if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
+ sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP ||
+ sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE) {
wpa_auth_set_eapol(sm->wpa_auth, sm->addr,
WPA_EAPOL_authorized, 1);
}
@@ -2451,9 +3382,9 @@ SM_STATE(WPA_PTK, PTKINITDONE)
"pairwise key handshake completed (%s)",
sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN");
-#ifdef CONFIG_IEEE80211R
+#ifdef CONFIG_IEEE80211R_AP
wpa_ft_push_pmk_r1(sm->wpa_auth, sm->addr);
-#endif /* CONFIG_IEEE80211R */
+#endif /* CONFIG_IEEE80211R_AP */
}
@@ -2497,15 +3428,22 @@ SM_STEP(WPA_PTK)
wpa_auth_get_eapol(sm->wpa_auth, sm->addr,
WPA_EAPOL_keyRun) > 0)
SM_ENTER(WPA_PTK, INITPMK);
- else if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)
+ else if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
+ sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE
/* FIX: && 802.1X::keyRun */)
SM_ENTER(WPA_PTK, INITPSK);
+ else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP)
+ SM_ENTER(WPA_PTK, INITPMK);
break;
case WPA_PTK_INITPMK:
if (wpa_auth_get_eapol(sm->wpa_auth, sm->addr,
- WPA_EAPOL_keyAvailable) > 0)
+ WPA_EAPOL_keyAvailable) > 0) {
+ SM_ENTER(WPA_PTK, PTKSTART);
+#ifdef CONFIG_DPP
+ } else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && sm->pmksa) {
SM_ENTER(WPA_PTK, PTKSTART);
- else {
+#endif /* CONFIG_DPP */
+ } else {
wpa_auth->dot11RSNA4WayHandshakeFailures++;
wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO,
"INITPMK - keyAvailable = false");
@@ -2514,9 +3452,13 @@ SM_STEP(WPA_PTK)
break;
case WPA_PTK_INITPSK:
if (wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr,
- NULL))
+ NULL, NULL, NULL)) {
+ SM_ENTER(WPA_PTK, PTKSTART);
+#ifdef CONFIG_SAE
+ } else if (wpa_auth_uses_sae(sm) && sm->pmksa) {
SM_ENTER(WPA_PTK, PTKSTART);
- else {
+#endif /* CONFIG_SAE */
+ } else {
wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO,
"no PSK configured for the STA");
wpa_auth->dot11RSNA4WayHandshakeFailures++;
@@ -2528,11 +3470,12 @@ SM_STEP(WPA_PTK)
sm->EAPOLKeyPairwise)
SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
else if (sm->TimeoutCtr >
- (int) dot11RSNAConfigPairwiseUpdateCount) {
+ sm->wpa_auth->conf.wpa_pairwise_update_count) {
wpa_auth->dot11RSNA4WayHandshakeFailures++;
- wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
- "PTKSTART: Retry limit %d reached",
- dot11RSNAConfigPairwiseUpdateCount);
+ wpa_auth_vlogger(
+ sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ "PTKSTART: Retry limit %u reached",
+ sm->wpa_auth->conf.wpa_pairwise_update_count);
SM_ENTER(WPA_PTK, DISCONNECT);
} else if (sm->TimeoutEvt)
SM_ENTER(WPA_PTK, PTKSTART);
@@ -2556,12 +3499,14 @@ SM_STEP(WPA_PTK)
sm->EAPOLKeyPairwise && sm->MICVerified)
SM_ENTER(WPA_PTK, PTKINITDONE);
else if (sm->TimeoutCtr >
- (int) dot11RSNAConfigPairwiseUpdateCount) {
+ sm->wpa_auth->conf.wpa_pairwise_update_count ||
+ (sm->wpa_auth->conf.wpa_disable_eapol_key_retries &&
+ sm->TimeoutCtr > 1)) {
wpa_auth->dot11RSNA4WayHandshakeFailures++;
- wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
- "PTKINITNEGOTIATING: Retry limit %d "
- "reached",
- dot11RSNAConfigPairwiseUpdateCount);
+ wpa_auth_vlogger(
+ sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ "PTKINITNEGOTIATING: Retry limit %u reached",
+ sm->wpa_auth->conf.wpa_pairwise_update_count);
SM_ENTER(WPA_PTK, DISCONNECT);
} else if (sm->TimeoutEvt)
SM_ENTER(WPA_PTK, PTKINITNEGOTIATING);
@@ -2596,7 +3541,12 @@ SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING)
SM_ENTRY_MA(WPA_PTK_GROUP, REKEYNEGOTIATING, wpa_ptk_group);
sm->GTimeoutCtr++;
- if (sm->GTimeoutCtr > (int) dot11RSNAConfigGroupUpdateCount) {
+ if (sm->wpa_auth->conf.wpa_disable_eapol_key_retries &&
+ sm->GTimeoutCtr > 1) {
+ /* Do not allow retransmission of EAPOL-Key group msg 1/2 */
+ return;
+ }
+ if (sm->GTimeoutCtr > sm->wpa_auth->conf.wpa_group_update_count) {
/* No point in sending the EAPOL-Key - we will disconnect
* immediately following this. */
return;
@@ -2613,7 +3563,8 @@ SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING)
"sending 1/2 msg of Group Key Handshake");
gtk = gsm->GTK[gsm->GN - 1];
- if (sm->wpa_auth->conf.disable_gtk) {
+ if (sm->wpa_auth->conf.disable_gtk ||
+ sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
/*
* Provide unique random GTK to each STA to prevent use
* of GTK in the BSS.
@@ -2624,7 +3575,7 @@ SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING)
}
if (sm->wpa == WPA_VERSION_WPA2) {
kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len +
- ieee80211w_kde_len(sm);
+ ieee80211w_kde_len(sm) + ocv_oci_len(sm);
kde_buf = os_malloc(kde_len);
if (kde_buf == NULL)
return;
@@ -2635,6 +3586,10 @@ SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING)
pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
gtk, gsm->GTK_len);
pos = ieee80211w_kde_add(sm, pos);
+ if (ocv_oci_add(sm, &pos) < 0) {
+ os_free(kde_buf);
+ return;
+ }
kde_len = pos - kde;
} else {
kde = gtk;
@@ -2642,10 +3597,12 @@ SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING)
}
wpa_send_eapol(sm->wpa_auth, sm,
- WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
+ WPA_KEY_INFO_SECURE |
+ (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
+ WPA_KEY_INFO_MIC : 0) |
WPA_KEY_INFO_ACK |
(!sm->Pair ? WPA_KEY_INFO_INSTALL : 0),
- rsc, gsm->GNonce, kde, kde_len, gsm->GN, 1);
+ rsc, NULL, kde, kde_len, gsm->GN, 1);
os_free(kde_buf);
}
@@ -2653,8 +3610,67 @@ SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING)
SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED)
{
+#ifdef CONFIG_OCV
+ struct wpa_authenticator *wpa_auth = sm->wpa_auth;
+ const u8 *key_data, *mic;
+ struct ieee802_1x_hdr *hdr;
+ struct wpa_eapol_key *key;
+ struct wpa_eapol_ie_parse kde;
+ size_t mic_len;
+ u16 key_data_length;
+#endif /* CONFIG_OCV */
+
SM_ENTRY_MA(WPA_PTK_GROUP, REKEYESTABLISHED, wpa_ptk_group);
sm->EAPOLKeyReceived = FALSE;
+
+#ifdef CONFIG_OCV
+ mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
+
+ /*
+ * Note: last_rx_eapol_key length fields have already been validated in
+ * wpa_receive().
+ */
+ hdr = (struct ieee802_1x_hdr *) sm->last_rx_eapol_key;
+ key = (struct wpa_eapol_key *) (hdr + 1);
+ mic = (u8 *) (key + 1);
+ key_data = mic + mic_len + 2;
+ key_data_length = WPA_GET_BE16(mic + mic_len);
+ if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) -
+ sizeof(*key) - mic_len - 2)
+ return;
+
+ if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) {
+ wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
+ "received EAPOL-Key group msg 2/2 with invalid Key Data contents");
+ return;
+ }
+
+ if (wpa_auth_uses_ocv(sm)) {
+ struct wpa_channel_info ci;
+ int tx_chanwidth;
+ int tx_seg1_idx;
+
+ if (wpa_channel_info(wpa_auth, &ci) != 0) {
+ wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ "Failed to get channel info to validate received OCI in EAPOL-Key group 1/2");
+ return;
+ }
+
+ if (get_sta_tx_parameters(sm,
+ channel_width_to_int(ci.chanwidth),
+ ci.seg1_idx, &tx_chanwidth,
+ &tx_seg1_idx) < 0)
+ return;
+
+ if (ocv_verify_tx_params(kde.oci, kde.oci_len, &ci,
+ tx_chanwidth, tx_seg1_idx) != 0) {
+ wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ ocv_errorstr);
+ return;
+ }
+ }
+#endif /* CONFIG_OCV */
+
if (sm->GUpdateStationKeys)
sm->group->GKeyDoneStations--;
sm->GUpdateStationKeys = FALSE;
@@ -2674,6 +3690,10 @@ SM_STATE(WPA_PTK_GROUP, KEYERROR)
sm->group->GKeyDoneStations--;
sm->GUpdateStationKeys = FALSE;
sm->Disconnect = TRUE;
+ wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO,
+ "group key handshake failed (%s) after %u tries",
+ sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN",
+ sm->wpa_auth->conf.wpa_group_update_count);
}
@@ -2693,7 +3713,9 @@ SM_STEP(WPA_PTK_GROUP)
!sm->EAPOLKeyPairwise && sm->MICVerified)
SM_ENTER(WPA_PTK_GROUP, REKEYESTABLISHED);
else if (sm->GTimeoutCtr >
- (int) dot11RSNAConfigGroupUpdateCount)
+ sm->wpa_auth->conf.wpa_group_update_count ||
+ (sm->wpa_auth->conf.wpa_disable_eapol_key_retries &&
+ sm->GTimeoutCtr > 1))
SM_ENTER(WPA_PTK_GROUP, KEYERROR);
else if (sm->TimeoutEvt)
SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING);
@@ -2796,7 +3818,7 @@ static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx)
}
-#ifdef CONFIG_WNM
+#ifdef CONFIG_WNM_AP
/* update GTK when exiting WNM-Sleep Mode */
void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm)
{
@@ -2875,7 +3897,7 @@ int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos)
return pos - start;
}
#endif /* CONFIG_IEEE80211W */
-#endif /* CONFIG_WNM */
+#endif /* CONFIG_WNM_AP */
static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth,
@@ -3153,8 +4175,8 @@ int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen)
"dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n",
RSN_VERSION,
!!wpa_auth->conf.wpa_strict_rekey,
- dot11RSNAConfigGroupUpdateCount,
- dot11RSNAConfigPairwiseUpdateCount,
+ wpa_auth->conf.wpa_group_update_count,
+ wpa_auth->conf.wpa_pairwise_update_count,
wpa_cipher_key_len(wpa_auth->conf.wpa_group) * 8,
dot11RSNAConfigPMKLifetime,
dot11RSNAConfigPMKReauthThreshold,
@@ -3257,6 +4279,15 @@ int wpa_auth_get_pairwise(struct wpa_state_machine *sm)
}
+const u8 * wpa_auth_get_pmk(struct wpa_state_machine *sm, int *len)
+{
+ if (!sm)
+ return NULL;
+ *len = sm->pmk_len;
+ return sm->PMK;
+}
+
+
int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm)
{
if (sm == NULL)
@@ -3281,6 +4312,14 @@ int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm)
}
+int wpa_auth_sta_fils_tk_already_set(struct wpa_state_machine *sm)
+{
+ if (!sm || !wpa_key_mgmt_fils(sm->wpa_key_mgmt))
+ return 0;
+ return sm->tk_already_set;
+}
+
+
int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm,
struct rsn_pmksa_cache_entry *entry)
{
@@ -3322,7 +4361,7 @@ int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk,
sm->wpa_auth->conf.disable_pmksa_caching)
return -1;
- if (sm->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
+ if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) {
if (pmk_len > PMK_LEN_SUITE_B_192)
pmk_len = PMK_LEN_SUITE_B_192;
} else if (pmk_len > PMK_LEN) {
@@ -3374,6 +4413,29 @@ int wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr,
}
+void wpa_auth_add_sae_pmkid(struct wpa_state_machine *sm, const u8 *pmkid)
+{
+ os_memcpy(sm->pmkid, pmkid, PMKID_LEN);
+ sm->pmkid_set = 1;
+}
+
+
+int wpa_auth_pmksa_add2(struct wpa_authenticator *wpa_auth, const u8 *addr,
+ const u8 *pmk, size_t pmk_len, const u8 *pmkid,
+ int session_timeout, int akmp)
+{
+ if (wpa_auth->conf.disable_pmksa_caching)
+ return -1;
+
+ if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, pmk_len, pmkid,
+ NULL, 0, wpa_auth->addr, addr, session_timeout,
+ NULL, akmp))
+ return 0;
+
+ return -1;
+}
+
+
void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth,
const u8 *sta_addr)
{
@@ -3406,12 +4468,65 @@ void wpa_auth_pmksa_flush(struct wpa_authenticator *wpa_auth)
}
+#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
+#ifdef CONFIG_MESH
+
+int wpa_auth_pmksa_list_mesh(struct wpa_authenticator *wpa_auth, const u8 *addr,
+ char *buf, size_t len)
+{
+ if (!wpa_auth || !wpa_auth->pmksa)
+ return 0;
+
+ return pmksa_cache_auth_list_mesh(wpa_auth->pmksa, addr, buf, len);
+}
+
+
struct rsn_pmksa_cache_entry *
-wpa_auth_pmksa_get(struct wpa_authenticator *wpa_auth, const u8 *sta_addr)
+wpa_auth_pmksa_create_entry(const u8 *aa, const u8 *spa, const u8 *pmk,
+ const u8 *pmkid, int expiration)
+{
+ struct rsn_pmksa_cache_entry *entry;
+ struct os_reltime now;
+
+ entry = pmksa_cache_auth_create_entry(pmk, PMK_LEN, pmkid, NULL, 0, aa,
+ spa, 0, NULL, WPA_KEY_MGMT_SAE);
+ if (!entry)
+ return NULL;
+
+ os_get_reltime(&now);
+ entry->expiration = now.sec + expiration;
+ return entry;
+}
+
+
+int wpa_auth_pmksa_add_entry(struct wpa_authenticator *wpa_auth,
+ struct rsn_pmksa_cache_entry *entry)
+{
+ int ret;
+
+ if (!wpa_auth || !wpa_auth->pmksa)
+ return -1;
+
+ ret = pmksa_cache_auth_add_entry(wpa_auth->pmksa, entry);
+ if (ret < 0)
+ wpa_printf(MSG_DEBUG,
+ "RSN: Failed to store external PMKSA cache for "
+ MACSTR, MAC2STR(entry->spa));
+
+ return ret;
+}
+
+#endif /* CONFIG_MESH */
+#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
+
+
+struct rsn_pmksa_cache_entry *
+wpa_auth_pmksa_get(struct wpa_authenticator *wpa_auth, const u8 *sta_addr,
+ const u8 *pmkid)
{
if (!wpa_auth || !wpa_auth->pmksa)
return NULL;
- return pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, NULL);
+ return pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, pmkid);
}
@@ -3664,6 +4779,14 @@ void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth,
(timeout_ms % 1000) * 1000,
wpa_send_eapol_timeout, wpa_auth, sm);
}
+
+#ifdef CONFIG_TESTING_OPTIONS
+ if (sm->eapol_status_cb) {
+ sm->eapol_status_cb(sm->eapol_status_cb_ctx1,
+ sm->eapol_status_cb_ctx2);
+ sm->eapol_status_cb = NULL;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
}
@@ -3710,3 +4833,379 @@ void wpa_auth_reconfig_group_keys(struct wpa_authenticator *wpa_auth)
for (group = wpa_auth->group; group; group = group->next)
wpa_group_config_group_keys(wpa_auth, group);
}
+
+
+#ifdef CONFIG_FILS
+
+struct wpa_auth_fils_iter_data {
+ struct wpa_authenticator *auth;
+ const u8 *cache_id;
+ struct rsn_pmksa_cache_entry *pmksa;
+ const u8 *spa;
+ const u8 *pmkid;
+};
+
+
+static int wpa_auth_fils_iter(struct wpa_authenticator *a, void *ctx)
+{
+ struct wpa_auth_fils_iter_data *data = ctx;
+
+ if (a == data->auth || !a->conf.fils_cache_id_set ||
+ os_memcmp(a->conf.fils_cache_id, data->cache_id,
+ FILS_CACHE_ID_LEN) != 0)
+ return 0;
+ data->pmksa = pmksa_cache_auth_get(a->pmksa, data->spa, data->pmkid);
+ return data->pmksa != NULL;
+}
+
+
+struct rsn_pmksa_cache_entry *
+wpa_auth_pmksa_get_fils_cache_id(struct wpa_authenticator *wpa_auth,
+ const u8 *sta_addr, const u8 *pmkid)
+{
+ struct wpa_auth_fils_iter_data idata;
+
+ if (!wpa_auth->conf.fils_cache_id_set)
+ return NULL;
+ idata.auth = wpa_auth;
+ idata.cache_id = wpa_auth->conf.fils_cache_id;
+ idata.pmksa = NULL;
+ idata.spa = sta_addr;
+ idata.pmkid = pmkid;
+ wpa_auth_for_each_auth(wpa_auth, wpa_auth_fils_iter, &idata);
+ return idata.pmksa;
+}
+
+
+#ifdef CONFIG_IEEE80211R_AP
+int wpa_auth_write_fte(struct wpa_authenticator *wpa_auth, int use_sha384,
+ u8 *buf, size_t len)
+{
+ struct wpa_auth_config *conf = &wpa_auth->conf;
+
+ return wpa_write_ftie(conf, use_sha384, conf->r0_key_holder,
+ conf->r0_key_holder_len,
+ NULL, NULL, buf, len, NULL, 0);
+}
+#endif /* CONFIG_IEEE80211R_AP */
+
+
+void wpa_auth_get_fils_aead_params(struct wpa_state_machine *sm,
+ u8 *fils_anonce, u8 *fils_snonce,
+ u8 *fils_kek, size_t *fils_kek_len)
+{
+ os_memcpy(fils_anonce, sm->ANonce, WPA_NONCE_LEN);
+ os_memcpy(fils_snonce, sm->SNonce, WPA_NONCE_LEN);
+ os_memcpy(fils_kek, sm->PTK.kek, WPA_KEK_MAX_LEN);
+ *fils_kek_len = sm->PTK.kek_len;
+}
+
+
+void wpa_auth_add_fils_pmk_pmkid(struct wpa_state_machine *sm, const u8 *pmk,
+ size_t pmk_len, const u8 *pmkid)
+{
+ os_memcpy(sm->PMK, pmk, pmk_len);
+ sm->pmk_len = pmk_len;
+ os_memcpy(sm->pmkid, pmkid, PMKID_LEN);
+ sm->pmkid_set = 1;
+}
+
+#endif /* CONFIG_FILS */
+
+
+void wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg)
+{
+ if (sm)
+ sm->auth_alg = auth_alg;
+}
+
+
+#ifdef CONFIG_DPP2
+void wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z)
+{
+ if (sm) {
+ wpabuf_clear_free(sm->dpp_z);
+ sm->dpp_z = z ? wpabuf_dup(z) : NULL;
+ }
+}
+#endif /* CONFIG_DPP2 */
+
+
+#ifdef CONFIG_TESTING_OPTIONS
+
+int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce,
+ void (*cb)(void *ctx1, void *ctx2),
+ void *ctx1, void *ctx2)
+{
+ const u8 *anonce = sm->ANonce;
+ u8 anonce_buf[WPA_NONCE_LEN];
+
+ if (change_anonce) {
+ if (random_get_bytes(anonce_buf, WPA_NONCE_LEN))
+ return -1;
+ anonce = anonce_buf;
+ }
+
+ wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ "sending 1/4 msg of 4-Way Handshake (TESTING)");
+ wpa_send_eapol(sm->wpa_auth, sm,
+ WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE, NULL,
+ anonce, NULL, 0, 0, 0);
+ return 0;
+}
+
+
+int wpa_auth_resend_m3(struct wpa_state_machine *sm,
+ void (*cb)(void *ctx1, void *ctx2),
+ void *ctx1, void *ctx2)
+{
+ u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos;
+#ifdef CONFIG_IEEE80211W
+ u8 *opos;
+#endif /* CONFIG_IEEE80211W */
+ size_t gtk_len, kde_len;
+ struct wpa_group *gsm = sm->group;
+ u8 *wpa_ie;
+ int wpa_ie_len, secure, keyidx, encr = 0;
+
+ /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE],
+ GTK[GN], IGTK, [FTIE], [TIE * 2])
+ */
+
+ /* Use 0 RSC */
+ os_memset(rsc, 0, WPA_KEY_RSC_LEN);
+ /* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */
+ wpa_ie = sm->wpa_auth->wpa_ie;
+ wpa_ie_len = sm->wpa_auth->wpa_ie_len;
+ if (sm->wpa == WPA_VERSION_WPA &&
+ (sm->wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
+ wpa_ie_len > wpa_ie[1] + 2 && wpa_ie[0] == WLAN_EID_RSN) {
+ /* WPA-only STA, remove RSN IE and possible MDIE */
+ wpa_ie = wpa_ie + wpa_ie[1] + 2;
+ if (wpa_ie[0] == WLAN_EID_MOBILITY_DOMAIN)
+ wpa_ie = wpa_ie + wpa_ie[1] + 2;
+ wpa_ie_len = wpa_ie[1] + 2;
+ }
+ wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ "sending 3/4 msg of 4-Way Handshake (TESTING)");
+ if (sm->wpa == WPA_VERSION_WPA2) {
+ /* WPA2 send GTK in the 4-way handshake */
+ secure = 1;
+ gtk = gsm->GTK[gsm->GN - 1];
+ gtk_len = gsm->GTK_len;
+ keyidx = gsm->GN;
+ _rsc = rsc;
+ encr = 1;
+ } else {
+ /* WPA does not include GTK in msg 3/4 */
+ secure = 0;
+ gtk = NULL;
+ gtk_len = 0;
+ keyidx = 0;
+ _rsc = NULL;
+ if (sm->rx_eapol_key_secure) {
+ /*
+ * It looks like Windows 7 supplicant tries to use
+ * Secure bit in msg 2/4 after having reported Michael
+ * MIC failure and it then rejects the 4-way handshake
+ * if msg 3/4 does not set Secure bit. Work around this
+ * by setting the Secure bit here even in the case of
+ * WPA if the supplicant used it first.
+ */
+ wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ "STA used Secure bit in WPA msg 2/4 - "
+ "set Secure for 3/4 as workaround");
+ secure = 1;
+ }
+ }
+
+ kde_len = wpa_ie_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm);
+ if (gtk)
+ kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len;
+#ifdef CONFIG_IEEE80211R_AP
+ if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
+ kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */
+ kde_len += 300; /* FTIE + 2 * TIE */
+ }
+#endif /* CONFIG_IEEE80211R_AP */
+ kde = os_malloc(kde_len);
+ if (kde == NULL)
+ return -1;
+
+ pos = kde;
+ os_memcpy(pos, wpa_ie, wpa_ie_len);
+ pos += wpa_ie_len;
+#ifdef CONFIG_IEEE80211R_AP
+ if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
+ int res;
+ size_t elen;
+
+ elen = pos - kde;
+ res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name);
+ if (res < 0) {
+ wpa_printf(MSG_ERROR, "FT: Failed to insert "
+ "PMKR1Name into RSN IE in EAPOL-Key data");
+ os_free(kde);
+ return -1;
+ }
+ pos -= wpa_ie_len;
+ pos += elen;
+ }
+#endif /* CONFIG_IEEE80211R_AP */
+ if (gtk) {
+ u8 hdr[2];
+ hdr[0] = keyidx & 0x03;
+ hdr[1] = 0;
+ pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
+ gtk, gtk_len);
+ }
+#ifdef CONFIG_IEEE80211W
+ opos = pos;
+ pos = ieee80211w_kde_add(sm, pos);
+ if (pos - opos >= 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN) {
+ /* skip KDE header and keyid */
+ opos += 2 + RSN_SELECTOR_LEN + 2;
+ os_memset(opos, 0, 6); /* clear PN */
+ }
+#endif /* CONFIG_IEEE80211W */
+ if (ocv_oci_add(sm, &pos) < 0) {
+ os_free(kde);
+ return -1;
+ }
+
+#ifdef CONFIG_IEEE80211R_AP
+ if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
+ int res;
+ struct wpa_auth_config *conf;
+
+ conf = &sm->wpa_auth->conf;
+ if (sm->assoc_resp_ftie &&
+ kde + kde_len - pos >= 2 + sm->assoc_resp_ftie[1]) {
+ os_memcpy(pos, sm->assoc_resp_ftie,
+ 2 + sm->assoc_resp_ftie[1]);
+ res = 2 + sm->assoc_resp_ftie[1];
+ } else {
+ int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
+
+ res = wpa_write_ftie(conf, use_sha384,
+ conf->r0_key_holder,
+ conf->r0_key_holder_len,
+ NULL, NULL, pos,
+ kde + kde_len - pos,
+ NULL, 0);
+ }
+ if (res < 0) {
+ wpa_printf(MSG_ERROR, "FT: Failed to insert FTIE "
+ "into EAPOL-Key Key Data");
+ os_free(kde);
+ return -1;
+ }
+ pos += res;
+
+ /* TIE[ReassociationDeadline] (TU) */
+ *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
+ *pos++ = 5;
+ *pos++ = WLAN_TIMEOUT_REASSOC_DEADLINE;
+ WPA_PUT_LE32(pos, conf->reassociation_deadline);
+ pos += 4;
+
+ /* TIE[KeyLifetime] (seconds) */
+ *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
+ *pos++ = 5;
+ *pos++ = WLAN_TIMEOUT_KEY_LIFETIME;
+ WPA_PUT_LE32(pos, conf->r0_key_lifetime);
+ pos += 4;
+ }
+#endif /* CONFIG_IEEE80211R_AP */
+
+ wpa_send_eapol(sm->wpa_auth, sm,
+ (secure ? WPA_KEY_INFO_SECURE : 0) |
+ (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
+ WPA_KEY_INFO_MIC : 0) |
+ WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL |
+ WPA_KEY_INFO_KEY_TYPE,
+ _rsc, sm->ANonce, kde, pos - kde, keyidx, encr);
+ os_free(kde);
+ return 0;
+}
+
+
+int wpa_auth_resend_group_m1(struct wpa_state_machine *sm,
+ void (*cb)(void *ctx1, void *ctx2),
+ void *ctx1, void *ctx2)
+{
+ u8 rsc[WPA_KEY_RSC_LEN];
+ struct wpa_group *gsm = sm->group;
+ const u8 *kde;
+ u8 *kde_buf = NULL, *pos, hdr[2];
+#ifdef CONFIG_IEEE80211W
+ u8 *opos;
+#endif /* CONFIG_IEEE80211W */
+ size_t kde_len;
+ u8 *gtk;
+
+ /* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */
+ os_memset(rsc, 0, WPA_KEY_RSC_LEN);
+ /* Use 0 RSC */
+ wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ "sending 1/2 msg of Group Key Handshake (TESTING)");
+
+ gtk = gsm->GTK[gsm->GN - 1];
+ if (sm->wpa == WPA_VERSION_WPA2) {
+ kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len +
+ ieee80211w_kde_len(sm) + ocv_oci_len(sm);
+ kde_buf = os_malloc(kde_len);
+ if (kde_buf == NULL)
+ return -1;
+
+ kde = pos = kde_buf;
+ hdr[0] = gsm->GN & 0x03;
+ hdr[1] = 0;
+ pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
+ gtk, gsm->GTK_len);
+#ifdef CONFIG_IEEE80211W
+ opos = pos;
+ pos = ieee80211w_kde_add(sm, pos);
+ if (pos - opos >=
+ 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN) {
+ /* skip KDE header and keyid */
+ opos += 2 + RSN_SELECTOR_LEN + 2;
+ os_memset(opos, 0, 6); /* clear PN */
+ }
+#endif /* CONFIG_IEEE80211W */
+ if (ocv_oci_add(sm, &pos) < 0) {
+ os_free(kde_buf);
+ return -1;
+ }
+ kde_len = pos - kde;
+ } else {
+ kde = gtk;
+ kde_len = gsm->GTK_len;
+ }
+
+ sm->eapol_status_cb = cb;
+ sm->eapol_status_cb_ctx1 = ctx1;
+ sm->eapol_status_cb_ctx2 = ctx2;
+
+ wpa_send_eapol(sm->wpa_auth, sm,
+ WPA_KEY_INFO_SECURE |
+ (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
+ WPA_KEY_INFO_MIC : 0) |
+ WPA_KEY_INFO_ACK |
+ (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0),
+ rsc, NULL, kde, kde_len, gsm->GN, 1);
+
+ os_free(kde_buf);
+ return 0;
+}
+
+
+int wpa_auth_rekey_gtk(struct wpa_authenticator *wpa_auth)
+{
+ if (!wpa_auth)
+ return -1;
+ eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
+ return eloop_register_timeout(0, 0, wpa_rekey_gtk, wpa_auth, NULL);
+}
+
+#endif /* CONFIG_TESTING_OPTIONS */
diff --git a/freebsd/contrib/wpa/src/ap/wpa_auth.h b/freebsd/contrib/wpa/src/ap/wpa_auth.h
index 97461b02..df1e17a0 100644
--- a/freebsd/contrib/wpa/src/ap/wpa_auth.h
+++ b/freebsd/contrib/wpa/src/ap/wpa_auth.h
@@ -1,6 +1,6 @@
/*
* hostapd - IEEE 802.11i-2004 / WPA Authenticator
- * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2017, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -14,6 +14,8 @@
#include "common/wpa_common.h"
#include "common/ieee802_11_defs.h"
+struct vlan_description;
+
#define MAX_OWN_IE_OVERRIDE 256
#ifdef _MSC_VER
@@ -37,74 +39,100 @@ struct ft_rrb_frame {
#define FT_PACKET_REQUEST 0
#define FT_PACKET_RESPONSE 1
-/* Vendor-specific types for R0KH-R1KH protocol; not defined in 802.11r */
-#define FT_PACKET_R0KH_R1KH_PULL 200
-#define FT_PACKET_R0KH_R1KH_RESP 201
-#define FT_PACKET_R0KH_R1KH_PUSH 202
-
-#define FT_R0KH_R1KH_PULL_NONCE_LEN 16
-#define FT_R0KH_R1KH_PULL_DATA_LEN (FT_R0KH_R1KH_PULL_NONCE_LEN + \
- WPA_PMK_NAME_LEN + FT_R1KH_ID_LEN + \
- ETH_ALEN)
-#define FT_R0KH_R1KH_PULL_PAD_LEN ((8 - FT_R0KH_R1KH_PULL_DATA_LEN % 8) % 8)
-
-struct ft_r0kh_r1kh_pull_frame {
- u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
- u8 packet_type; /* FT_PACKET_R0KH_R1KH_PULL */
- le16 data_length; /* little endian length of data (44) */
- u8 ap_address[ETH_ALEN];
- u8 nonce[FT_R0KH_R1KH_PULL_NONCE_LEN];
- u8 pmk_r0_name[WPA_PMK_NAME_LEN];
- u8 r1kh_id[FT_R1KH_ID_LEN];
- u8 s1kh_id[ETH_ALEN];
- u8 pad[FT_R0KH_R1KH_PULL_PAD_LEN]; /* 8-octet boundary for AES block */
- u8 key_wrap_extra[8];
-} STRUCT_PACKED;
+/* Vendor-specific types for R0KH-R1KH protocol; not defined in 802.11r. These
+ * use OUI Extended EtherType as the encapsulating format. */
+#define FT_PACKET_R0KH_R1KH_PULL 0x01
+#define FT_PACKET_R0KH_R1KH_RESP 0x02
+#define FT_PACKET_R0KH_R1KH_PUSH 0x03
+#define FT_PACKET_R0KH_R1KH_SEQ_REQ 0x04
+#define FT_PACKET_R0KH_R1KH_SEQ_RESP 0x05
+
+/* packet layout
+ * IEEE 802 extended OUI ethertype frame header
+ * u16 authlen (little endian)
+ * multiple of struct ft_rrb_tlv (authenticated only, length = authlen)
+ * multiple of struct ft_rrb_tlv (AES-SIV encrypted, AES-SIV needs an extra
+ * blocksize length)
+ *
+ * AES-SIV AAD;
+ * source MAC address (6)
+ * authenticated-only TLVs (authlen)
+ * subtype (1; FT_PACKET_*)
+ */
-#define FT_R0KH_R1KH_RESP_DATA_LEN (FT_R0KH_R1KH_PULL_NONCE_LEN + \
- FT_R1KH_ID_LEN + ETH_ALEN + PMK_LEN + \
- WPA_PMK_NAME_LEN + 2)
-#define FT_R0KH_R1KH_RESP_PAD_LEN ((8 - FT_R0KH_R1KH_RESP_DATA_LEN % 8) % 8)
-struct ft_r0kh_r1kh_resp_frame {
- u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
- u8 packet_type; /* FT_PACKET_R0KH_R1KH_RESP */
- le16 data_length; /* little endian length of data (78) */
- u8 ap_address[ETH_ALEN];
+#define FT_RRB_NONCE_LEN 16
- u8 nonce[FT_R0KH_R1KH_PULL_NONCE_LEN]; /* copied from pull */
- u8 r1kh_id[FT_R1KH_ID_LEN]; /* copied from pull */
- u8 s1kh_id[ETH_ALEN]; /* copied from pull */
- u8 pmk_r1[PMK_LEN];
- u8 pmk_r1_name[WPA_PMK_NAME_LEN];
- le16 pairwise;
- u8 pad[FT_R0KH_R1KH_RESP_PAD_LEN]; /* 8-octet boundary for AES block */
- u8 key_wrap_extra[8];
-} STRUCT_PACKED;
+#define FT_RRB_LAST_EMPTY 0 /* placeholder or padding */
-#define FT_R0KH_R1KH_PUSH_DATA_LEN (4 + FT_R1KH_ID_LEN + ETH_ALEN + \
- WPA_PMK_NAME_LEN + PMK_LEN + \
- WPA_PMK_NAME_LEN + 2)
-#define FT_R0KH_R1KH_PUSH_PAD_LEN ((8 - FT_R0KH_R1KH_PUSH_DATA_LEN % 8) % 8)
-struct ft_r0kh_r1kh_push_frame {
- u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
- u8 packet_type; /* FT_PACKET_R0KH_R1KH_PUSH */
- le16 data_length; /* little endian length of data (82) */
- u8 ap_address[ETH_ALEN];
+#define FT_RRB_SEQ 1 /* struct ft_rrb_seq */
+#define FT_RRB_NONCE 2 /* size FT_RRB_NONCE_LEN */
+#define FT_RRB_TIMESTAMP 3 /* le32 unix seconds */
+
+#define FT_RRB_R0KH_ID 4 /* FT_R0KH_ID_MAX_LEN */
+#define FT_RRB_R1KH_ID 5 /* FT_R1KH_ID_LEN */
+#define FT_RRB_S1KH_ID 6 /* ETH_ALEN */
+
+#define FT_RRB_PMK_R0_NAME 7 /* WPA_PMK_NAME_LEN */
+#define FT_RRB_PMK_R0 8 /* PMK_LEN */
+#define FT_RRB_PMK_R1_NAME 9 /* WPA_PMK_NAME_LEN */
+#define FT_RRB_PMK_R1 10 /* PMK_LEN */
+
+#define FT_RRB_PAIRWISE 11 /* le16 */
+#define FT_RRB_EXPIRES_IN 12 /* le16 seconds */
+
+#define FT_RRB_VLAN_UNTAGGED 13 /* le16 */
+#define FT_RRB_VLAN_TAGGED 14 /* n times le16 */
- /* Encrypted with AES key-wrap */
- u8 timestamp[4]; /* current time in seconds since unix epoch, little
- * endian */
- u8 r1kh_id[FT_R1KH_ID_LEN];
- u8 s1kh_id[ETH_ALEN];
- u8 pmk_r0_name[WPA_PMK_NAME_LEN];
- u8 pmk_r1[PMK_LEN];
- u8 pmk_r1_name[WPA_PMK_NAME_LEN];
- le16 pairwise;
- u8 pad[FT_R0KH_R1KH_PUSH_PAD_LEN]; /* 8-octet boundary for AES block */
- u8 key_wrap_extra[8];
+#define FT_RRB_IDENTITY 15
+#define FT_RRB_RADIUS_CUI 16
+#define FT_RRB_SESSION_TIMEOUT 17 /* le32 seconds */
+
+struct ft_rrb_tlv {
+ le16 type;
+ le16 len;
+ /* followed by data of length len */
+} STRUCT_PACKED;
+
+struct ft_rrb_seq {
+ le32 dom;
+ le32 seq;
+ le32 ts;
} STRUCT_PACKED;
+/* session TLVs:
+ * required: PMK_R1, PMK_R1_NAME, PAIRWISE
+ * optional: VLAN_UNTAGGED, VLAN_TAGGED, EXPIRES_IN, IDENTITY, RADIUS_CUI,
+ * SESSION_TIMEOUT
+ *
+ * pull frame TLVs:
+ * auth:
+ * required: SEQ, NONCE, R0KH_ID, R1KH_ID
+ * encrypted:
+ * required: PMK_R0_NAME, S1KH_ID
+ *
+ * response frame TLVs:
+ * auth:
+ * required: SEQ, NONCE, R0KH_ID, R1KH_ID
+ * encrypted:
+ * required: S1KH_ID
+ * optional: session TLVs
+ *
+ * push frame TLVs:
+ * auth:
+ * required: SEQ, R0KH_ID, R1KH_ID
+ * encrypted:
+ * required: S1KH_ID, PMK_R0_NAME, session TLVs
+ *
+ * sequence number request frame TLVs:
+ * auth:
+ * required: R0KH_ID, R1KH_ID, NONCE
+ *
+ * sequence number response frame TLVs:
+ * auth:
+ * required: SEQ, NONCE, R0KH_ID, R1KH_ID
+ */
+
#ifdef _MSC_VER
#pragma pack(pop)
#endif /* _MSC_VER */
@@ -116,6 +144,8 @@ struct wpa_authenticator;
struct wpa_state_machine;
struct rsn_pmksa_cache_entry;
struct eapol_state_machine;
+struct ft_remote_seq;
+struct wpa_channel_info;
struct ft_remote_r0kh {
@@ -123,7 +153,8 @@ struct ft_remote_r0kh {
u8 addr[ETH_ALEN];
u8 id[FT_R0KH_ID_MAX_LEN];
size_t id_len;
- u8 key[16];
+ u8 key[32];
+ struct ft_remote_seq *seq;
};
@@ -131,7 +162,8 @@ struct ft_remote_r1kh {
struct ft_remote_r1kh *next;
u8 addr[ETH_ALEN];
u8 id[FT_R1KH_ID_LEN];
- u8 key[16];
+ u8 key[32];
+ struct ft_remote_seq *seq;
};
@@ -144,10 +176,12 @@ struct wpa_auth_config {
int wpa_strict_rekey;
int wpa_gmk_rekey;
int wpa_ptk_rekey;
+ u32 wpa_group_update_count;
+ u32 wpa_pairwise_update_count;
+ int wpa_disable_eapol_key_retries;
int rsn_pairwise;
int rsn_preauth;
int eapol_version;
- int peerkey;
int wmm_enabled;
int wmm_uapsd;
int disable_pmksa_caching;
@@ -156,21 +190,31 @@ struct wpa_auth_config {
#ifdef CONFIG_IEEE80211W
enum mfp_options ieee80211w;
int group_mgmt_cipher;
+ int sae_require_mfp;
#endif /* CONFIG_IEEE80211W */
-#ifdef CONFIG_IEEE80211R
+#ifdef CONFIG_OCV
+ int ocv; /* Operating Channel Validation */
+#endif /* CONFIG_OCV */
+#ifdef CONFIG_IEEE80211R_AP
u8 ssid[SSID_MAX_LEN];
size_t ssid_len;
u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN];
u8 r0_key_holder[FT_R0KH_ID_MAX_LEN];
size_t r0_key_holder_len;
u8 r1_key_holder[FT_R1KH_ID_LEN];
- u32 r0_key_lifetime;
+ u32 r0_key_lifetime; /* PMK-R0 lifetime seconds */
+ int rkh_pos_timeout;
+ int rkh_neg_timeout;
+ int rkh_pull_timeout; /* ms */
+ int rkh_pull_retries;
+ int r1_max_key_lifetime;
u32 reassociation_deadline;
- struct ft_remote_r0kh *r0kh_list;
- struct ft_remote_r1kh *r1kh_list;
+ struct ft_remote_r0kh **r0kh_list;
+ struct ft_remote_r1kh **r1kh_list;
int pmk_r1_push;
int ft_over_ds;
-#endif /* CONFIG_IEEE80211R */
+ int ft_psk_generate_local;
+#endif /* CONFIG_IEEE80211R_AP */
int disable_gtk;
int ap_mlme;
#ifdef CONFIG_TESTING_OPTIONS
@@ -184,6 +228,10 @@ struct wpa_auth_config {
u8 ip_addr_start[4];
u8 ip_addr_end[4];
#endif /* CONFIG_P2P */
+#ifdef CONFIG_FILS
+ unsigned int fils_cache_id_set:1;
+ u8 fils_cache_id[FILS_CACHE_ID_LEN];
+#endif /* CONFIG_FILS */
};
typedef enum {
@@ -197,7 +245,6 @@ typedef enum {
} wpa_eapol_variable;
struct wpa_auth_callbacks {
- void *ctx;
void (*logger)(void *ctx, const u8 *addr, logger_level level,
const char *txt);
void (*disconnect)(void *ctx, const u8 *addr, u16 reason);
@@ -207,7 +254,8 @@ struct wpa_auth_callbacks {
int value);
int (*get_eapol)(void *ctx, const u8 *addr, wpa_eapol_variable var);
const u8 * (*get_psk)(void *ctx, const u8 *addr, const u8 *p2p_dev_addr,
- const u8 *prev_psk);
+ const u8 *prev_psk, size_t *psk_len,
+ int *vlan_id);
int (*get_msk)(void *ctx, const u8 *addr, u8 *msk, size_t *len);
int (*set_key)(void *ctx, int vlan_id, enum wpa_alg alg,
const u8 *addr, int idx, u8 *key, size_t key_len);
@@ -220,13 +268,34 @@ struct wpa_auth_callbacks {
void *ctx), void *cb_ctx);
int (*send_ether)(void *ctx, const u8 *dst, u16 proto, const u8 *data,
size_t data_len);
-#ifdef CONFIG_IEEE80211R
+ int (*send_oui)(void *ctx, const u8 *dst, u8 oui_suffix, const u8 *data,
+ size_t data_len);
+ int (*channel_info)(void *ctx, struct wpa_channel_info *ci);
+ int (*update_vlan)(void *ctx, const u8 *addr, int vlan_id);
+ int (*get_sta_tx_params)(void *ctx, const u8 *addr,
+ int ap_max_chanwidth, int ap_seg1_idx,
+ int *bandwidth, int *seg1_idx);
+#ifdef CONFIG_IEEE80211R_AP
struct wpa_state_machine * (*add_sta)(void *ctx, const u8 *sta_addr);
+ int (*set_vlan)(void *ctx, const u8 *sta_addr,
+ struct vlan_description *vlan);
+ int (*get_vlan)(void *ctx, const u8 *sta_addr,
+ struct vlan_description *vlan);
+ int (*set_identity)(void *ctx, const u8 *sta_addr,
+ const u8 *identity, size_t identity_len);
+ size_t (*get_identity)(void *ctx, const u8 *sta_addr, const u8 **buf);
+ int (*set_radius_cui)(void *ctx, const u8 *sta_addr,
+ const u8 *radius_cui, size_t radius_cui_len);
+ size_t (*get_radius_cui)(void *ctx, const u8 *sta_addr, const u8 **buf);
+ void (*set_session_timeout)(void *ctx, const u8 *sta_addr,
+ int session_timeout);
+ int (*get_session_timeout)(void *ctx, const u8 *sta_addr);
+
int (*send_ft_action)(void *ctx, const u8 *dst,
const u8 *data, size_t data_len);
int (*add_tspec)(void *ctx, const u8 *sta_addr, u8 *tspec_ie,
size_t tspec_ielen);
-#endif /* CONFIG_IEEE80211R */
+#endif /* CONFIG_IEEE80211R_AP */
#ifdef CONFIG_MESH
int (*start_ampe)(void *ctx, const u8 *sta_addr);
#endif /* CONFIG_MESH */
@@ -234,7 +303,8 @@ struct wpa_auth_callbacks {
struct wpa_authenticator * wpa_init(const u8 *addr,
struct wpa_auth_config *conf,
- struct wpa_auth_callbacks *cb);
+ const struct wpa_auth_callbacks *cb,
+ void *cb_ctx);
int wpa_init_keys(struct wpa_authenticator *wpa_auth);
void wpa_deinit(struct wpa_authenticator *wpa_auth);
int wpa_reconfig(struct wpa_authenticator *wpa_auth,
@@ -244,17 +314,20 @@ enum {
WPA_IE_OK, WPA_INVALID_IE, WPA_INVALID_GROUP, WPA_INVALID_PAIRWISE,
WPA_INVALID_AKMP, WPA_NOT_ENABLED, WPA_ALLOC_FAIL,
WPA_MGMT_FRAME_PROTECTION_VIOLATION, WPA_INVALID_MGMT_GROUP_CIPHER,
- WPA_INVALID_MDIE, WPA_INVALID_PROTO
+ WPA_INVALID_MDIE, WPA_INVALID_PROTO, WPA_INVALID_PMKID
};
-
+
int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
- struct wpa_state_machine *sm,
+ struct wpa_state_machine *sm, int freq,
const u8 *wpa_ie, size_t wpa_ie_len,
- const u8 *mdie, size_t mdie_len);
+ const u8 *mdie, size_t mdie_len,
+ const u8 *owe_dh, size_t owe_dh_len);
int wpa_validate_osen(struct wpa_authenticator *wpa_auth,
struct wpa_state_machine *sm,
const u8 *osen_ie, size_t osen_ie_len);
int wpa_auth_uses_mfp(struct wpa_state_machine *sm);
+void wpa_auth_set_ocv(struct wpa_state_machine *sm, int ocv);
+int wpa_auth_uses_ocv(struct wpa_state_machine *sm);
struct wpa_state_machine *
wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr,
const u8 *p2p_dev_addr);
@@ -267,7 +340,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
u8 *data, size_t data_len);
enum wpa_event {
WPA_AUTH, WPA_ASSOC, WPA_DISASSOC, WPA_DEAUTH, WPA_REAUTH,
- WPA_REAUTH_EAPOL, WPA_ASSOC_FT, WPA_DRV_STA_REMOVED
+ WPA_REAUTH_EAPOL, WPA_ASSOC_FT, WPA_ASSOC_FILS, WPA_DRV_STA_REMOVED
};
void wpa_remove_ptk(struct wpa_state_machine *sm);
int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event);
@@ -278,9 +351,11 @@ int wpa_get_mib_sta(struct wpa_state_machine *sm, char *buf, size_t buflen);
void wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth);
int wpa_auth_pairwise_set(struct wpa_state_machine *sm);
int wpa_auth_get_pairwise(struct wpa_state_machine *sm);
+const u8 * wpa_auth_get_pmk(struct wpa_state_machine *sm, int *len);
int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm);
int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm);
int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm);
+int wpa_auth_sta_fils_tk_already_set(struct wpa_state_machine *sm);
int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm,
struct rsn_pmksa_cache_entry *entry);
struct rsn_pmksa_cache_entry *
@@ -297,13 +372,28 @@ int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
struct eapol_state_machine *eapol);
int wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr,
const u8 *pmk, const u8 *pmkid);
+void wpa_auth_add_sae_pmkid(struct wpa_state_machine *sm, const u8 *pmkid);
+int wpa_auth_pmksa_add2(struct wpa_authenticator *wpa_auth, const u8 *addr,
+ const u8 *pmk, size_t pmk_len, const u8 *pmkid,
+ int session_timeout, int akmp);
void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth,
const u8 *sta_addr);
int wpa_auth_pmksa_list(struct wpa_authenticator *wpa_auth, char *buf,
size_t len);
void wpa_auth_pmksa_flush(struct wpa_authenticator *wpa_auth);
+int wpa_auth_pmksa_list_mesh(struct wpa_authenticator *wpa_auth, const u8 *addr,
+ char *buf, size_t len);
+struct rsn_pmksa_cache_entry *
+wpa_auth_pmksa_create_entry(const u8 *aa, const u8 *spa, const u8 *pmk,
+ const u8 *pmkid, int expiration);
+int wpa_auth_pmksa_add_entry(struct wpa_authenticator *wpa_auth,
+ struct rsn_pmksa_cache_entry *entry);
+struct rsn_pmksa_cache_entry *
+wpa_auth_pmksa_get(struct wpa_authenticator *wpa_auth, const u8 *sta_addr,
+ const u8 *pmkid);
struct rsn_pmksa_cache_entry *
-wpa_auth_pmksa_get(struct wpa_authenticator *wpa_auth, const u8 *sta_addr);
+wpa_auth_pmksa_get_fils_cache_id(struct wpa_authenticator *wpa_auth,
+ const u8 *sta_addr, const u8 *pmkid);
void wpa_auth_pmksa_set_to_sm(struct rsn_pmksa_cache_entry *pmksa,
struct wpa_state_machine *sm,
struct wpa_authenticator *wpa_auth,
@@ -312,7 +402,7 @@ int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id);
void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth,
struct wpa_state_machine *sm, int ack);
-#ifdef CONFIG_IEEE80211R
+#ifdef CONFIG_IEEE80211R_AP
u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
size_t max_len, int auth_alg,
const u8 *req_ies, size_t req_ies_len);
@@ -327,8 +417,13 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
int wpa_ft_action_rx(struct wpa_state_machine *sm, const u8 *data, size_t len);
int wpa_ft_rrb_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr,
const u8 *data, size_t data_len);
+void wpa_ft_rrb_oui_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr,
+ const u8 *dst_addr, u8 oui_suffix, const u8 *data,
+ size_t data_len);
void wpa_ft_push_pmk_r1(struct wpa_authenticator *wpa_auth, const u8 *addr);
-#endif /* CONFIG_IEEE80211R */
+void wpa_ft_deinit(struct wpa_authenticator *wpa_auth);
+void wpa_ft_sta_deinit(struct wpa_state_machine *sm);
+#endif /* CONFIG_IEEE80211R_AP */
void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm);
void wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag);
@@ -347,5 +442,52 @@ void wpa_auth_reconfig_group_keys(struct wpa_authenticator *wpa_auth);
int wpa_auth_ensure_group(struct wpa_authenticator *wpa_auth, int vlan_id);
int wpa_auth_release_group(struct wpa_authenticator *wpa_auth, int vlan_id);
+int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk,
+ size_t pmk_len, const u8 *snonce, const u8 *anonce,
+ const u8 *dhss, size_t dhss_len,
+ struct wpabuf *g_sta, struct wpabuf *g_ap);
+int fils_decrypt_assoc(struct wpa_state_machine *sm, const u8 *fils_session,
+ const struct ieee80211_mgmt *mgmt, size_t frame_len,
+ u8 *pos, size_t left);
+int fils_encrypt_assoc(struct wpa_state_machine *sm, u8 *buf,
+ size_t current_len, size_t max_len,
+ const struct wpabuf *hlp);
+int fils_set_tk(struct wpa_state_machine *sm);
+u8 * hostapd_eid_assoc_fils_session(struct wpa_state_machine *sm, u8 *eid,
+ const u8 *fils_session,
+ struct wpabuf *fils_hlp_resp);
+const u8 * wpa_fils_validate_fils_session(struct wpa_state_machine *sm,
+ const u8 *ies, size_t ies_len,
+ const u8 *fils_session);
+int wpa_fils_validate_key_confirm(struct wpa_state_machine *sm, const u8 *ies,
+ size_t ies_len);
+
+int get_sta_tx_parameters(struct wpa_state_machine *sm, int ap_max_chanwidth,
+ int ap_seg1_idx, int *bandwidth, int *seg1_idx);
+
+int wpa_auth_write_fte(struct wpa_authenticator *wpa_auth, int use_sha384,
+ u8 *buf, size_t len);
+void wpa_auth_get_fils_aead_params(struct wpa_state_machine *sm,
+ u8 *fils_anonce, u8 *fils_snonce,
+ u8 *fils_kek, size_t *fils_kek_len);
+void wpa_auth_add_fils_pmk_pmkid(struct wpa_state_machine *sm, const u8 *pmk,
+ size_t pmk_len, const u8 *pmkid);
+u8 * wpa_auth_write_assoc_resp_owe(struct wpa_state_machine *sm,
+ u8 *pos, size_t max_len,
+ const u8 *req_ies, size_t req_ies_len);
+void wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg);
+void wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z);
+
+int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce,
+ void (*cb)(void *ctx1, void *ctx2),
+ void *ctx1, void *ctx2);
+int wpa_auth_resend_m3(struct wpa_state_machine *sm,
+ void (*cb)(void *ctx1, void *ctx2),
+ void *ctx1, void *ctx2);
+int wpa_auth_resend_group_m1(struct wpa_state_machine *sm,
+ void (*cb)(void *ctx1, void *ctx2),
+ void *ctx1, void *ctx2);
+int wpa_auth_rekey_gtk(struct wpa_authenticator *wpa_auth);
+void wpa_auth_set_ptk_rekey_timer(struct wpa_state_machine *sm);
#endif /* WPA_AUTH_H */
diff --git a/freebsd/contrib/wpa/src/ap/wpa_auth_ft.c b/freebsd/contrib/wpa/src/ap/wpa_auth_ft.c
index fe145fad..e2eaacbd 100644
--- a/freebsd/contrib/wpa/src/ap/wpa_auth_ft.c
+++ b/freebsd/contrib/wpa/src/ap/wpa_auth_ft.c
@@ -2,7 +2,7 @@
/*
* hostapd - IEEE 802.11r - Fast BSS Transition
- * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -15,7 +15,12 @@
#include "utils/list.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
+#include "common/ocv.h"
+#include "drivers/driver.h"
+#include "crypto/aes.h"
+#include "crypto/aes_siv.h"
#include "crypto/aes_wrap.h"
+#include "crypto/sha384.h"
#include "crypto/random.h"
#include "ap_config.h"
#include "ieee802_11.h"
@@ -24,41 +29,735 @@
#include "wpa_auth_i.h"
-#ifdef CONFIG_IEEE80211R
+#ifdef CONFIG_IEEE80211R_AP
+
+const unsigned int ftRRBseqTimeout = 10;
+const unsigned int ftRRBmaxQueueLen = 100;
+
static int wpa_ft_send_rrb_auth_resp(struct wpa_state_machine *sm,
const u8 *current_ap, const u8 *sta_addr,
u16 status, const u8 *resp_ies,
size_t resp_ies_len);
+static void ft_finish_pull(struct wpa_state_machine *sm);
+static void wpa_ft_expire_pull(void *eloop_ctx, void *timeout_ctx);
+static void wpa_ft_rrb_seq_timeout(void *eloop_ctx, void *timeout_ctx);
+
+struct tlv_list {
+ u16 type;
+ size_t len;
+ const u8 *data;
+};
+
+
+/**
+ * wpa_ft_rrb_decrypt - Decrypt FT RRB message
+ * @key: AES-SIV key for AEAD
+ * @key_len: Length of key in octets
+ * @enc: Pointer to encrypted TLVs
+ * @enc_len: Length of encrypted TLVs in octets
+ * @auth: Pointer to authenticated TLVs
+ * @auth_len: Length of authenticated TLVs in octets
+ * @src_addr: MAC address of the frame sender
+ * @type: Vendor-specific subtype of the RRB frame (FT_PACKET_*)
+ * @plain: Pointer to return the pointer to the allocated plaintext buffer;
+ * needs to be freed by the caller if not NULL;
+ * will only be returned on success
+ * @plain_len: Pointer to return the length of the allocated plaintext buffer
+ * in octets
+ * Returns: 0 on success, -1 on error
+ */
+static int wpa_ft_rrb_decrypt(const u8 *key, const size_t key_len,
+ const u8 *enc, size_t enc_len,
+ const u8 *auth, const size_t auth_len,
+ const u8 *src_addr, u8 type,
+ u8 **plain, size_t *plain_size)
+{
+ const u8 *ad[3] = { src_addr, auth, &type };
+ size_t ad_len[3] = { ETH_ALEN, auth_len, sizeof(type) };
+
+ wpa_printf(MSG_DEBUG, "FT(RRB): src_addr=" MACSTR " type=%u",
+ MAC2STR(src_addr), type);
+ wpa_hexdump_key(MSG_DEBUG, "FT(RRB): decrypt using key", key, key_len);
+ wpa_hexdump(MSG_DEBUG, "FT(RRB): encrypted TLVs", enc, enc_len);
+ wpa_hexdump(MSG_DEBUG, "FT(RRB): authenticated TLVs", auth, auth_len);
+
+ if (!key) { /* skip decryption */
+ *plain = os_memdup(enc, enc_len);
+ if (enc_len > 0 && !*plain)
+ goto err;
+
+ *plain_size = enc_len;
+
+ return 0;
+ }
+
+ *plain = NULL;
+
+ /* SIV overhead */
+ if (enc_len < AES_BLOCK_SIZE)
+ goto err;
+
+ *plain = os_zalloc(enc_len - AES_BLOCK_SIZE);
+ if (!*plain)
+ goto err;
+
+ if (aes_siv_decrypt(key, key_len, enc, enc_len, 3, ad, ad_len,
+ *plain) < 0) {
+ if (enc_len < AES_BLOCK_SIZE + 2)
+ goto err;
+
+ /* Try to work around Ethernet devices that add extra
+ * two octet padding even if the frame is longer than
+ * the minimum Ethernet frame. */
+ enc_len -= 2;
+ if (aes_siv_decrypt(key, key_len, enc, enc_len, 3, ad, ad_len,
+ *plain) < 0)
+ goto err;
+ }
+
+ *plain_size = enc_len - AES_BLOCK_SIZE;
+ wpa_hexdump_key(MSG_DEBUG, "FT(RRB): decrypted TLVs",
+ *plain, *plain_size);
+ return 0;
+err:
+ os_free(*plain);
+ *plain = NULL;
+ *plain_size = 0;
+
+ wpa_printf(MSG_ERROR, "FT(RRB): Failed to decrypt");
+
+ return -1;
+}
+
+
+/* get first tlv record in packet matching type
+ * @data (decrypted) packet
+ * @return 0 on success else -1
+ */
+static int wpa_ft_rrb_get_tlv(const u8 *plain, size_t plain_len,
+ u16 type, size_t *tlv_len, const u8 **tlv_data)
+{
+ const struct ft_rrb_tlv *f;
+ size_t left;
+ le16 type16;
+ size_t len;
+ left = plain_len;
+ type16 = host_to_le16(type);
+
+ while (left >= sizeof(*f)) {
+ f = (const struct ft_rrb_tlv *) plain;
+
+ left -= sizeof(*f);
+ plain += sizeof(*f);
+ len = le_to_host16(f->len);
+
+ if (left < len) {
+ wpa_printf(MSG_DEBUG, "FT: RRB message truncated");
+ break;
+ }
+
+ if (f->type == type16) {
+ *tlv_len = len;
+ *tlv_data = plain;
+ return 0;
+ }
+
+ left -= len;
+ plain += len;
+ }
+
+ return -1;
+}
+
+
+static void wpa_ft_rrb_dump(const u8 *plain, const size_t plain_len)
+{
+ const struct ft_rrb_tlv *f;
+ size_t left;
+ size_t len;
+
+ left = plain_len;
+
+ wpa_printf(MSG_DEBUG, "FT: RRB dump message");
+ while (left >= sizeof(*f)) {
+ f = (const struct ft_rrb_tlv *) plain;
+
+ left -= sizeof(*f);
+ plain += sizeof(*f);
+ len = le_to_host16(f->len);
+
+ wpa_printf(MSG_DEBUG, "FT: RRB TLV type = %d, len = %zu",
+ le_to_host16(f->type), len);
+
+ if (left < len) {
+ wpa_printf(MSG_DEBUG,
+ "FT: RRB message truncated: left %zu bytes, need %zu",
+ left, len);
+ break;
+ }
+
+ wpa_hexdump(MSG_DEBUG, "FT: RRB TLV data", plain, len);
+
+ left -= len;
+ plain += len;
+ }
+
+ if (left > 0)
+ wpa_hexdump(MSG_DEBUG, "FT: RRB TLV padding", plain, left);
+
+ wpa_printf(MSG_DEBUG, "FT: RRB dump message end");
+}
+
+
+static int cmp_int(const void *a, const void *b)
+{
+ int x, y;
+
+ x = *((int *) a);
+ y = *((int *) b);
+ return x - y;
+}
+
+
+static int wpa_ft_rrb_get_tlv_vlan(const u8 *plain, const size_t plain_len,
+ struct vlan_description *vlan)
+{
+ struct ft_rrb_tlv *f;
+ size_t left;
+ size_t len;
+ int taggedidx;
+ int vlan_id;
+ int type;
+
+ left = plain_len;
+ taggedidx = 0;
+ os_memset(vlan, 0, sizeof(*vlan));
+
+ while (left >= sizeof(*f)) {
+ f = (struct ft_rrb_tlv *) plain;
+
+ left -= sizeof(*f);
+ plain += sizeof(*f);
+
+ len = le_to_host16(f->len);
+ type = le_to_host16(f->type);
+
+ if (left < len) {
+ wpa_printf(MSG_DEBUG, "FT: RRB message truncated");
+ return -1;
+ }
+
+ if (type != FT_RRB_VLAN_UNTAGGED && type != FT_RRB_VLAN_TAGGED)
+ goto skip;
+
+ if (type == FT_RRB_VLAN_UNTAGGED && len != sizeof(le16)) {
+ wpa_printf(MSG_DEBUG,
+ "FT: RRB VLAN_UNTAGGED invalid length");
+ return -1;
+ }
+
+ if (type == FT_RRB_VLAN_TAGGED && len % sizeof(le16) != 0) {
+ wpa_printf(MSG_DEBUG,
+ "FT: RRB VLAN_TAGGED invalid length");
+ return -1;
+ }
+
+ while (len >= sizeof(le16)) {
+ vlan_id = WPA_GET_LE16(plain);
+ plain += sizeof(le16);
+ left -= sizeof(le16);
+ len -= sizeof(le16);
+
+ if (vlan_id <= 0 || vlan_id > MAX_VLAN_ID) {
+ wpa_printf(MSG_DEBUG,
+ "FT: RRB VLAN ID invalid %d",
+ vlan_id);
+ continue;
+ }
+
+ if (type == FT_RRB_VLAN_UNTAGGED)
+ vlan->untagged = vlan_id;
+
+ if (type == FT_RRB_VLAN_TAGGED &&
+ taggedidx < MAX_NUM_TAGGED_VLAN) {
+ vlan->tagged[taggedidx] = vlan_id;
+ taggedidx++;
+ } else if (type == FT_RRB_VLAN_TAGGED) {
+ wpa_printf(MSG_DEBUG, "FT: RRB too many VLANs");
+ }
+ }
+
+ skip:
+ left -= len;
+ plain += len;
+ }
+
+ if (taggedidx)
+ qsort(vlan->tagged, taggedidx, sizeof(int), cmp_int);
+
+ vlan->notempty = vlan->untagged || vlan->tagged[0];
+
+ return 0;
+}
+
+
+static size_t wpa_ft_tlv_len(const struct tlv_list *tlvs)
+{
+ size_t tlv_len = 0;
+ int i;
+
+ if (!tlvs)
+ return 0;
+
+ for (i = 0; tlvs[i].type != FT_RRB_LAST_EMPTY; i++) {
+ tlv_len += sizeof(struct ft_rrb_tlv);
+ tlv_len += tlvs[i].len;
+ }
+
+ return tlv_len;
+}
+
+
+static size_t wpa_ft_tlv_lin(const struct tlv_list *tlvs, u8 *start,
+ u8 *endpos)
+{
+ int i;
+ size_t tlv_len;
+ struct ft_rrb_tlv *hdr;
+ u8 *pos;
+
+ if (!tlvs)
+ return 0;
+
+ tlv_len = 0;
+ pos = start;
+ for (i = 0; tlvs[i].type != FT_RRB_LAST_EMPTY; i++) {
+ if (tlv_len + sizeof(*hdr) > (size_t) (endpos - start))
+ return tlv_len;
+ tlv_len += sizeof(*hdr);
+ hdr = (struct ft_rrb_tlv *) pos;
+ hdr->type = host_to_le16(tlvs[i].type);
+ hdr->len = host_to_le16(tlvs[i].len);
+ pos = start + tlv_len;
+
+ if (tlv_len + tlvs[i].len > (size_t) (endpos - start))
+ return tlv_len;
+ if (tlvs[i].len == 0)
+ continue;
+ tlv_len += tlvs[i].len;
+ os_memcpy(pos, tlvs[i].data, tlvs[i].len);
+ pos = start + tlv_len;
+ }
+
+ return tlv_len;
+}
+
+
+static size_t wpa_ft_vlan_len(const struct vlan_description *vlan)
+{
+ size_t tlv_len = 0;
+ int i;
+
+ if (!vlan || !vlan->notempty)
+ return 0;
+
+ if (vlan->untagged) {
+ tlv_len += sizeof(struct ft_rrb_tlv);
+ tlv_len += sizeof(le16);
+ }
+ if (vlan->tagged[0])
+ tlv_len += sizeof(struct ft_rrb_tlv);
+ for (i = 0; i < MAX_NUM_TAGGED_VLAN && vlan->tagged[i]; i++)
+ tlv_len += sizeof(le16);
+
+ return tlv_len;
+}
+
+
+static size_t wpa_ft_vlan_lin(const struct vlan_description *vlan,
+ u8 *start, u8 *endpos)
+{
+ size_t tlv_len;
+ int i, len;
+ struct ft_rrb_tlv *hdr;
+ u8 *pos = start;
+
+ if (!vlan || !vlan->notempty)
+ return 0;
+
+ tlv_len = 0;
+ if (vlan->untagged) {
+ tlv_len += sizeof(*hdr);
+ if (start + tlv_len > endpos)
+ return tlv_len;
+ hdr = (struct ft_rrb_tlv *) pos;
+ hdr->type = host_to_le16(FT_RRB_VLAN_UNTAGGED);
+ hdr->len = host_to_le16(sizeof(le16));
+ pos = start + tlv_len;
+
+ tlv_len += sizeof(le16);
+ if (start + tlv_len > endpos)
+ return tlv_len;
+ WPA_PUT_LE16(pos, vlan->untagged);
+ pos = start + tlv_len;
+ }
+
+ if (!vlan->tagged[0])
+ return tlv_len;
+
+ tlv_len += sizeof(*hdr);
+ if (start + tlv_len > endpos)
+ return tlv_len;
+ hdr = (struct ft_rrb_tlv *) pos;
+ hdr->type = host_to_le16(FT_RRB_VLAN_TAGGED);
+ len = 0; /* len is computed below */
+ pos = start + tlv_len;
+
+ for (i = 0; i < MAX_NUM_TAGGED_VLAN && vlan->tagged[i]; i++) {
+ tlv_len += sizeof(le16);
+ if (start + tlv_len > endpos)
+ break;
+ len += sizeof(le16);
+ WPA_PUT_LE16(pos, vlan->tagged[i]);
+ pos = start + tlv_len;
+ }
+
+ hdr->len = host_to_le16(len);
+
+ return tlv_len;
+}
+
+
+static int wpa_ft_rrb_lin(const struct tlv_list *tlvs1,
+ const struct tlv_list *tlvs2,
+ const struct vlan_description *vlan,
+ u8 **plain, size_t *plain_len)
+{
+ u8 *pos, *endpos;
+ size_t tlv_len;
+
+ tlv_len = wpa_ft_tlv_len(tlvs1);
+ tlv_len += wpa_ft_tlv_len(tlvs2);
+ tlv_len += wpa_ft_vlan_len(vlan);
+
+ *plain_len = tlv_len;
+ *plain = os_zalloc(tlv_len);
+ if (!*plain) {
+ wpa_printf(MSG_ERROR, "FT: Failed to allocate plaintext");
+ goto err;
+ }
+
+ pos = *plain;
+ endpos = *plain + tlv_len;
+ pos += wpa_ft_tlv_lin(tlvs1, pos, endpos);
+ pos += wpa_ft_tlv_lin(tlvs2, pos, endpos);
+ pos += wpa_ft_vlan_lin(vlan, pos, endpos);
+
+ /* sanity check */
+ if (pos != endpos) {
+ wpa_printf(MSG_ERROR, "FT: Length error building RRB");
+ goto err;
+ }
+
+ return 0;
+
+err:
+ os_free(*plain);
+ *plain = NULL;
+ *plain_len = 0;
+ return -1;
+}
+
+
+static int wpa_ft_rrb_encrypt(const u8 *key, const size_t key_len,
+ const u8 *plain, const size_t plain_len,
+ const u8 *auth, const size_t auth_len,
+ const u8 *src_addr, u8 type, u8 *enc)
+{
+ const u8 *ad[3] = { src_addr, auth, &type };
+ size_t ad_len[3] = { ETH_ALEN, auth_len, sizeof(type) };
+
+ wpa_printf(MSG_DEBUG, "FT(RRB): src_addr=" MACSTR " type=%u",
+ MAC2STR(src_addr), type);
+ wpa_hexdump_key(MSG_DEBUG, "FT(RRB): plaintext message",
+ plain, plain_len);
+ wpa_hexdump_key(MSG_DEBUG, "FT(RRB): encrypt using key", key, key_len);
+ wpa_hexdump(MSG_DEBUG, "FT(RRB): authenticated TLVs", auth, auth_len);
+
+ if (!key) {
+ /* encryption not needed, return plaintext as packet */
+ os_memcpy(enc, plain, plain_len);
+ } else if (aes_siv_encrypt(key, key_len, plain, plain_len,
+ 3, ad, ad_len, enc) < 0) {
+ wpa_printf(MSG_ERROR, "FT: Failed to encrypt RRB-OUI message");
+ return -1;
+ }
+ wpa_hexdump(MSG_DEBUG, "FT(RRB): encrypted TLVs",
+ enc, plain_len + AES_BLOCK_SIZE);
+
+ return 0;
+}
+
+
+/**
+ * wpa_ft_rrb_build - Build and encrypt an FT RRB message
+ * @key: AES-SIV key for AEAD
+ * @key_len: Length of key in octets
+ * @tlvs_enc0: First set of to-be-encrypted TLVs
+ * @tlvs_enc1: Second set of to-be-encrypted TLVs
+ * @tlvs_auth: Set of to-be-authenticated TLVs
+ * @src_addr: MAC address of the frame sender
+ * @type: Vendor-specific subtype of the RRB frame (FT_PACKET_*)
+ * @packet Pointer to return the pointer to the allocated packet buffer;
+ * needs to be freed by the caller if not null;
+ * will only be returned on success
+ * @packet_len: Pointer to return the length of the allocated buffer in octets
+ * Returns: 0 on success, -1 on error
+ */
+static int wpa_ft_rrb_build(const u8 *key, const size_t key_len,
+ const struct tlv_list *tlvs_enc0,
+ const struct tlv_list *tlvs_enc1,
+ const struct tlv_list *tlvs_auth,
+ const struct vlan_description *vlan,
+ const u8 *src_addr, u8 type,
+ u8 **packet, size_t *packet_len)
+{
+ u8 *plain = NULL, *auth = NULL, *pos, *tmp;
+ size_t plain_len = 0, auth_len = 0;
+ int ret = -1;
+ size_t pad_len = 0;
+
+ *packet = NULL;
+ if (wpa_ft_rrb_lin(tlvs_enc0, tlvs_enc1, vlan, &plain, &plain_len) < 0)
+ goto out;
+
+ if (wpa_ft_rrb_lin(tlvs_auth, NULL, NULL, &auth, &auth_len) < 0)
+ goto out;
+
+ *packet_len = sizeof(u16) + auth_len + plain_len;
+ if (key)
+ *packet_len += AES_BLOCK_SIZE;
+#define RRB_MIN_MSG_LEN 64
+ if (*packet_len < RRB_MIN_MSG_LEN) {
+ pad_len = RRB_MIN_MSG_LEN - *packet_len;
+ if (pad_len < sizeof(struct ft_rrb_tlv))
+ pad_len = sizeof(struct ft_rrb_tlv);
+ wpa_printf(MSG_DEBUG,
+ "FT: Pad message to minimum Ethernet frame length (%d --> %d)",
+ (int) *packet_len, (int) (*packet_len + pad_len));
+ *packet_len += pad_len;
+ tmp = os_realloc(auth, auth_len + pad_len);
+ if (!tmp)
+ goto out;
+ auth = tmp;
+ pos = auth + auth_len;
+ WPA_PUT_LE16(pos, FT_RRB_LAST_EMPTY);
+ pos += 2;
+ WPA_PUT_LE16(pos, pad_len - sizeof(struct ft_rrb_tlv));
+ pos += 2;
+ os_memset(pos, 0, pad_len - sizeof(struct ft_rrb_tlv));
+ auth_len += pad_len;
+
+ }
+ *packet = os_zalloc(*packet_len);
+ if (!*packet)
+ goto out;
+
+ pos = *packet;
+ WPA_PUT_LE16(pos, auth_len);
+ pos += 2;
+ os_memcpy(pos, auth, auth_len);
+ pos += auth_len;
+ if (wpa_ft_rrb_encrypt(key, key_len, plain, plain_len, auth,
+ auth_len, src_addr, type, pos) < 0)
+ goto out;
+ wpa_hexdump(MSG_MSGDUMP, "FT: RRB frame payload", *packet, *packet_len);
+
+ ret = 0;
+
+out:
+ bin_clear_free(plain, plain_len);
+ os_free(auth);
+
+ if (ret) {
+ wpa_printf(MSG_ERROR, "FT: Failed to build RRB-OUI message");
+ os_free(*packet);
+ *packet = NULL;
+ *packet_len = 0;
+ }
+
+ return ret;
+}
+
+
+#define RRB_GET_SRC(srcfield, type, field, txt, checklength) do { \
+ if (wpa_ft_rrb_get_tlv(srcfield, srcfield##_len, type, \
+ &f_##field##_len, &f_##field) < 0 || \
+ (checklength > 0 && ((size_t) checklength) != f_##field##_len)) { \
+ wpa_printf(MSG_INFO, "FT: Missing required " #field \
+ " in %s from " MACSTR, txt, MAC2STR(src_addr)); \
+ wpa_ft_rrb_dump(srcfield, srcfield##_len); \
+ goto out; \
+ } \
+} while (0)
+
+#define RRB_GET(type, field, txt, checklength) \
+ RRB_GET_SRC(plain, type, field, txt, checklength)
+#define RRB_GET_AUTH(type, field, txt, checklength) \
+ RRB_GET_SRC(auth, type, field, txt, checklength)
+
+#define RRB_GET_OPTIONAL_SRC(srcfield, type, field, txt, checklength) do { \
+ if (wpa_ft_rrb_get_tlv(srcfield, srcfield##_len, type, \
+ &f_##field##_len, &f_##field) < 0 || \
+ (checklength > 0 && ((size_t) checklength) != f_##field##_len)) { \
+ wpa_printf(MSG_DEBUG, "FT: Missing optional " #field \
+ " in %s from " MACSTR, txt, MAC2STR(src_addr)); \
+ f_##field##_len = 0; \
+ f_##field = NULL; \
+ } \
+} while (0)
+
+#define RRB_GET_OPTIONAL(type, field, txt, checklength) \
+ RRB_GET_OPTIONAL_SRC(plain, type, field, txt, checklength)
+#define RRB_GET_OPTIONAL_AUTH(type, field, txt, checklength) \
+ RRB_GET_OPTIONAL_SRC(auth, type, field, txt, checklength)
static int wpa_ft_rrb_send(struct wpa_authenticator *wpa_auth, const u8 *dst,
const u8 *data, size_t data_len)
{
- if (wpa_auth->cb.send_ether == NULL)
+ if (wpa_auth->cb->send_ether == NULL)
return -1;
wpa_printf(MSG_DEBUG, "FT: RRB send to " MACSTR, MAC2STR(dst));
- return wpa_auth->cb.send_ether(wpa_auth->cb.ctx, dst, ETH_P_RRB,
- data, data_len);
+ return wpa_auth->cb->send_ether(wpa_auth->cb_ctx, dst, ETH_P_RRB,
+ data, data_len);
+}
+
+
+static int wpa_ft_rrb_oui_send(struct wpa_authenticator *wpa_auth,
+ const u8 *dst, u8 oui_suffix,
+ const u8 *data, size_t data_len)
+{
+ if (!wpa_auth->cb->send_oui)
+ return -1;
+ wpa_printf(MSG_DEBUG, "FT: RRB-OUI type %u send to " MACSTR " (len=%u)",
+ oui_suffix, MAC2STR(dst), (unsigned int) data_len);
+ return wpa_auth->cb->send_oui(wpa_auth->cb_ctx, dst, oui_suffix, data,
+ data_len);
}
static int wpa_ft_action_send(struct wpa_authenticator *wpa_auth,
const u8 *dst, const u8 *data, size_t data_len)
{
- if (wpa_auth->cb.send_ft_action == NULL)
+ if (wpa_auth->cb->send_ft_action == NULL)
return -1;
- return wpa_auth->cb.send_ft_action(wpa_auth->cb.ctx, dst,
- data, data_len);
+ return wpa_auth->cb->send_ft_action(wpa_auth->cb_ctx, dst,
+ data, data_len);
+}
+
+
+static const u8 * wpa_ft_get_psk(struct wpa_authenticator *wpa_auth,
+ const u8 *addr, const u8 *p2p_dev_addr,
+ const u8 *prev_psk)
+{
+ if (wpa_auth->cb->get_psk == NULL)
+ return NULL;
+ return wpa_auth->cb->get_psk(wpa_auth->cb_ctx, addr, p2p_dev_addr,
+ prev_psk, NULL, NULL);
}
static struct wpa_state_machine *
wpa_ft_add_sta(struct wpa_authenticator *wpa_auth, const u8 *sta_addr)
{
- if (wpa_auth->cb.add_sta == NULL)
+ if (wpa_auth->cb->add_sta == NULL)
return NULL;
- return wpa_auth->cb.add_sta(wpa_auth->cb.ctx, sta_addr);
+ return wpa_auth->cb->add_sta(wpa_auth->cb_ctx, sta_addr);
+}
+
+
+static int wpa_ft_set_vlan(struct wpa_authenticator *wpa_auth,
+ const u8 *sta_addr, struct vlan_description *vlan)
+{
+ if (!wpa_auth->cb->set_vlan)
+ return -1;
+ return wpa_auth->cb->set_vlan(wpa_auth->cb_ctx, sta_addr, vlan);
+}
+
+
+static int wpa_ft_get_vlan(struct wpa_authenticator *wpa_auth,
+ const u8 *sta_addr, struct vlan_description *vlan)
+{
+ if (!wpa_auth->cb->get_vlan)
+ return -1;
+ return wpa_auth->cb->get_vlan(wpa_auth->cb_ctx, sta_addr, vlan);
+}
+
+
+static int
+wpa_ft_set_identity(struct wpa_authenticator *wpa_auth, const u8 *sta_addr,
+ const u8 *identity, size_t identity_len)
+{
+ if (!wpa_auth->cb->set_identity)
+ return -1;
+ return wpa_auth->cb->set_identity(wpa_auth->cb_ctx, sta_addr, identity,
+ identity_len);
+}
+
+
+static size_t
+wpa_ft_get_identity(struct wpa_authenticator *wpa_auth, const u8 *sta_addr,
+ const u8 **buf)
+{
+ *buf = NULL;
+ if (!wpa_auth->cb->get_identity)
+ return 0;
+ return wpa_auth->cb->get_identity(wpa_auth->cb_ctx, sta_addr, buf);
+}
+
+
+static int
+wpa_ft_set_radius_cui(struct wpa_authenticator *wpa_auth, const u8 *sta_addr,
+ const u8 *radius_cui, size_t radius_cui_len)
+{
+ if (!wpa_auth->cb->set_radius_cui)
+ return -1;
+ return wpa_auth->cb->set_radius_cui(wpa_auth->cb_ctx, sta_addr,
+ radius_cui, radius_cui_len);
+}
+
+
+static size_t
+wpa_ft_get_radius_cui(struct wpa_authenticator *wpa_auth, const u8 *sta_addr,
+ const u8 **buf)
+{
+ *buf = NULL;
+ if (!wpa_auth->cb->get_radius_cui)
+ return 0;
+ return wpa_auth->cb->get_radius_cui(wpa_auth->cb_ctx, sta_addr, buf);
+}
+
+
+static void
+wpa_ft_set_session_timeout(struct wpa_authenticator *wpa_auth,
+ const u8 *sta_addr, int session_timeout)
+{
+ if (!wpa_auth->cb->set_session_timeout)
+ return;
+ wpa_auth->cb->set_session_timeout(wpa_auth->cb_ctx, sta_addr,
+ session_timeout);
+}
+
+
+static int
+wpa_ft_get_session_timeout(struct wpa_authenticator *wpa_auth,
+ const u8 *sta_addr)
+{
+ if (!wpa_auth->cb->get_session_timeout)
+ return 0;
+ return wpa_auth->cb->get_session_timeout(wpa_auth->cb_ctx, sta_addr);
}
@@ -66,15 +765,26 @@ static int wpa_ft_add_tspec(struct wpa_authenticator *wpa_auth,
const u8 *sta_addr,
u8 *tspec_ie, size_t tspec_ielen)
{
- if (wpa_auth->cb.add_tspec == NULL) {
+ if (wpa_auth->cb->add_tspec == NULL) {
wpa_printf(MSG_DEBUG, "FT: add_tspec is not initialized");
return -1;
}
- return wpa_auth->cb.add_tspec(wpa_auth->cb.ctx, sta_addr, tspec_ie,
- tspec_ielen);
+ return wpa_auth->cb->add_tspec(wpa_auth->cb_ctx, sta_addr, tspec_ie,
+ tspec_ielen);
}
+#ifdef CONFIG_OCV
+static int wpa_channel_info(struct wpa_authenticator *wpa_auth,
+ struct wpa_channel_info *ci)
+{
+ if (!wpa_auth->cb->channel_info)
+ return -1;
+ return wpa_auth->cb->channel_info(wpa_auth->cb_ctx, ci);
+}
+#endif /* CONFIG_OCV */
+
+
int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len)
{
u8 *pos = buf;
@@ -95,30 +805,44 @@ int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len)
}
-int wpa_write_ftie(struct wpa_auth_config *conf, const u8 *r0kh_id,
- size_t r0kh_id_len,
+int wpa_write_ftie(struct wpa_auth_config *conf, int use_sha384,
+ const u8 *r0kh_id, size_t r0kh_id_len,
const u8 *anonce, const u8 *snonce,
u8 *buf, size_t len, const u8 *subelem,
size_t subelem_len)
{
u8 *pos = buf, *ielen;
- struct rsn_ftie *hdr;
+ size_t hdrlen = use_sha384 ? sizeof(struct rsn_ftie_sha384) :
+ sizeof(struct rsn_ftie);
- if (len < 2 + sizeof(*hdr) + 2 + FT_R1KH_ID_LEN + 2 + r0kh_id_len +
+ if (len < 2 + hdrlen + 2 + FT_R1KH_ID_LEN + 2 + r0kh_id_len +
subelem_len)
return -1;
*pos++ = WLAN_EID_FAST_BSS_TRANSITION;
ielen = pos++;
- hdr = (struct rsn_ftie *) pos;
- os_memset(hdr, 0, sizeof(*hdr));
- pos += sizeof(*hdr);
- WPA_PUT_LE16(hdr->mic_control, 0);
- if (anonce)
- os_memcpy(hdr->anonce, anonce, WPA_NONCE_LEN);
- if (snonce)
- os_memcpy(hdr->snonce, snonce, WPA_NONCE_LEN);
+ if (use_sha384) {
+ struct rsn_ftie_sha384 *hdr = (struct rsn_ftie_sha384 *) pos;
+
+ os_memset(hdr, 0, sizeof(*hdr));
+ pos += sizeof(*hdr);
+ WPA_PUT_LE16(hdr->mic_control, 0);
+ if (anonce)
+ os_memcpy(hdr->anonce, anonce, WPA_NONCE_LEN);
+ if (snonce)
+ os_memcpy(hdr->snonce, snonce, WPA_NONCE_LEN);
+ } else {
+ struct rsn_ftie *hdr = (struct rsn_ftie *) pos;
+
+ os_memset(hdr, 0, sizeof(*hdr));
+ pos += sizeof(*hdr);
+ WPA_PUT_LE16(hdr->mic_control, 0);
+ if (anonce)
+ os_memcpy(hdr->anonce, anonce, WPA_NONCE_LEN);
+ if (snonce)
+ os_memcpy(hdr->snonce, snonce, WPA_NONCE_LEN);
+ }
/* Optional Parameters */
*pos++ = FTIE_SUBELEM_R1KH_ID;
@@ -144,35 +868,434 @@ int wpa_write_ftie(struct wpa_auth_config *conf, const u8 *r0kh_id,
}
+/* A packet to be handled after seq response */
+struct ft_remote_item {
+ struct dl_list list;
+
+ u8 nonce[FT_RRB_NONCE_LEN];
+ struct os_reltime nonce_ts;
+
+ u8 src_addr[ETH_ALEN];
+ u8 *enc;
+ size_t enc_len;
+ u8 *auth;
+ size_t auth_len;
+ int (*cb)(struct wpa_authenticator *wpa_auth,
+ const u8 *src_addr,
+ const u8 *enc, size_t enc_len,
+ const u8 *auth, size_t auth_len,
+ int no_defer);
+};
+
+
+static void wpa_ft_rrb_seq_free(struct ft_remote_item *item)
+{
+ eloop_cancel_timeout(wpa_ft_rrb_seq_timeout, ELOOP_ALL_CTX, item);
+ dl_list_del(&item->list);
+ bin_clear_free(item->enc, item->enc_len);
+ os_free(item->auth);
+ os_free(item);
+}
+
+
+static void wpa_ft_rrb_seq_flush(struct wpa_authenticator *wpa_auth,
+ struct ft_remote_seq *rkh_seq, int cb)
+{
+ struct ft_remote_item *item, *n;
+
+ dl_list_for_each_safe(item, n, &rkh_seq->rx.queue,
+ struct ft_remote_item, list) {
+ if (cb && item->cb)
+ item->cb(wpa_auth, item->src_addr, item->enc,
+ item->enc_len, item->auth, item->auth_len, 1);
+ wpa_ft_rrb_seq_free(item);
+ }
+}
+
+
+static void wpa_ft_rrb_seq_timeout(void *eloop_ctx, void *timeout_ctx)
+{
+ struct ft_remote_item *item = timeout_ctx;
+
+ wpa_ft_rrb_seq_free(item);
+}
+
+
+static int
+wpa_ft_rrb_seq_req(struct wpa_authenticator *wpa_auth,
+ struct ft_remote_seq *rkh_seq, const u8 *src_addr,
+ const u8 *f_r0kh_id, size_t f_r0kh_id_len,
+ const u8 *f_r1kh_id, const u8 *key, size_t key_len,
+ const u8 *enc, size_t enc_len,
+ const u8 *auth, size_t auth_len,
+ int (*cb)(struct wpa_authenticator *wpa_auth,
+ const u8 *src_addr,
+ const u8 *enc, size_t enc_len,
+ const u8 *auth, size_t auth_len,
+ int no_defer))
+{
+ struct ft_remote_item *item = NULL;
+ u8 *packet = NULL;
+ size_t packet_len;
+ struct tlv_list seq_req_auth[] = {
+ { .type = FT_RRB_NONCE, .len = FT_RRB_NONCE_LEN,
+ .data = NULL /* to be filled: item->nonce */ },
+ { .type = FT_RRB_R0KH_ID, .len = f_r0kh_id_len,
+ .data = f_r0kh_id },
+ { .type = FT_RRB_R1KH_ID, .len = FT_R1KH_ID_LEN,
+ .data = f_r1kh_id },
+ { .type = FT_RRB_LAST_EMPTY, .len = 0, .data = NULL },
+ };
+
+ if (dl_list_len(&rkh_seq->rx.queue) >= ftRRBmaxQueueLen) {
+ wpa_printf(MSG_DEBUG, "FT: Sequence number queue too long");
+ goto err;
+ }
+
+ wpa_printf(MSG_DEBUG, "FT: Send out sequence number request to " MACSTR,
+ MAC2STR(src_addr));
+ item = os_zalloc(sizeof(*item));
+ if (!item)
+ goto err;
+
+ os_memcpy(item->src_addr, src_addr, ETH_ALEN);
+ item->cb = cb;
+
+ if (random_get_bytes(item->nonce, FT_RRB_NONCE_LEN) < 0) {
+ wpa_printf(MSG_DEBUG, "FT: Seq num nonce: out of random bytes");
+ goto err;
+ }
+
+ if (os_get_reltime(&item->nonce_ts) < 0)
+ goto err;
+
+ if (enc && enc_len > 0) {
+ item->enc = os_memdup(enc, enc_len);
+ item->enc_len = enc_len;
+ if (!item->enc)
+ goto err;
+ }
+
+ if (auth && auth_len > 0) {
+ item->auth = os_memdup(auth, auth_len);
+ item->auth_len = auth_len;
+ if (!item->auth)
+ goto err;
+ }
+
+ eloop_register_timeout(ftRRBseqTimeout, 0, wpa_ft_rrb_seq_timeout,
+ wpa_auth, item);
+
+ seq_req_auth[0].data = item->nonce;
+
+ if (wpa_ft_rrb_build(key, key_len, NULL, NULL, seq_req_auth, NULL,
+ wpa_auth->addr, FT_PACKET_R0KH_R1KH_SEQ_REQ,
+ &packet, &packet_len) < 0) {
+ item = NULL; /* some other seq resp might still accept this */
+ goto err;
+ }
+
+ dl_list_add(&rkh_seq->rx.queue, &item->list);
+
+ wpa_ft_rrb_oui_send(wpa_auth, src_addr, FT_PACKET_R0KH_R1KH_SEQ_REQ,
+ packet, packet_len);
+
+ os_free(packet);
+
+ return 0;
+err:
+ wpa_printf(MSG_DEBUG, "FT: Failed to send sequence number request");
+ if (item) {
+ os_free(item->auth);
+ bin_clear_free(item->enc, item->enc_len);
+ os_free(item);
+ }
+
+ return -1;
+}
+
+
+#define FT_RRB_SEQ_OK 0
+#define FT_RRB_SEQ_DROP 1
+#define FT_RRB_SEQ_DEFER 2
+
+static int
+wpa_ft_rrb_seq_chk(struct ft_remote_seq *rkh_seq, const u8 *src_addr,
+ const u8 *enc, size_t enc_len,
+ const u8 *auth, size_t auth_len,
+ const char *msgtype, int no_defer)
+{
+ const u8 *f_seq;
+ size_t f_seq_len;
+ const struct ft_rrb_seq *msg_both;
+ u32 msg_seq, msg_off, rkh_off;
+ struct os_reltime now;
+ unsigned int i;
+
+ RRB_GET_AUTH(FT_RRB_SEQ, seq, msgtype, sizeof(*msg_both));
+ wpa_hexdump(MSG_DEBUG, "FT: sequence number", f_seq, f_seq_len);
+ msg_both = (const struct ft_rrb_seq *) f_seq;
+
+ if (rkh_seq->rx.num_last == 0) {
+ /* first packet from remote */
+ goto defer;
+ }
+
+ if (le_to_host32(msg_both->dom) != rkh_seq->rx.dom) {
+ /* remote might have rebooted */
+ goto defer;
+ }
+
+ if (os_get_reltime(&now) == 0) {
+ u32 msg_ts_now_remote, msg_ts_off;
+ struct os_reltime now_remote;
+
+ os_reltime_sub(&now, &rkh_seq->rx.time_offset, &now_remote);
+ msg_ts_now_remote = now_remote.sec;
+ msg_ts_off = le_to_host32(msg_both->ts) -
+ (msg_ts_now_remote - ftRRBseqTimeout);
+ if (msg_ts_off > 2 * ftRRBseqTimeout)
+ goto defer;
+ }
+
+ msg_seq = le_to_host32(msg_both->seq);
+ rkh_off = rkh_seq->rx.last[rkh_seq->rx.offsetidx];
+ msg_off = msg_seq - rkh_off;
+ if (msg_off > 0xC0000000)
+ goto out; /* too old message, drop it */
+
+ if (msg_off <= 0x40000000) {
+ for (i = 0; i < rkh_seq->rx.num_last; i++) {
+ if (rkh_seq->rx.last[i] == msg_seq)
+ goto out; /* duplicate message, drop it */
+ }
+
+ return FT_RRB_SEQ_OK;
+ }
+
+defer:
+ if (no_defer)
+ goto out;
+
+ wpa_printf(MSG_DEBUG, "FT: Possibly invalid sequence number in %s from "
+ MACSTR, msgtype, MAC2STR(src_addr));
+
+ return FT_RRB_SEQ_DEFER;
+out:
+ wpa_printf(MSG_DEBUG, "FT: Invalid sequence number in %s from " MACSTR,
+ msgtype, MAC2STR(src_addr));
+
+ return FT_RRB_SEQ_DROP;
+}
+
+
+static void
+wpa_ft_rrb_seq_accept(struct wpa_authenticator *wpa_auth,
+ struct ft_remote_seq *rkh_seq, const u8 *src_addr,
+ const u8 *auth, size_t auth_len,
+ const char *msgtype)
+{
+ const u8 *f_seq;
+ size_t f_seq_len;
+ const struct ft_rrb_seq *msg_both;
+ u32 msg_seq, msg_off, min_off, rkh_off;
+ int minidx = 0;
+ unsigned int i;
+
+ RRB_GET_AUTH(FT_RRB_SEQ, seq, msgtype, sizeof(*msg_both));
+ msg_both = (const struct ft_rrb_seq *) f_seq;
+
+ msg_seq = le_to_host32(msg_both->seq);
+
+ if (rkh_seq->rx.num_last < FT_REMOTE_SEQ_BACKLOG) {
+ rkh_seq->rx.last[rkh_seq->rx.num_last] = msg_seq;
+ rkh_seq->rx.num_last++;
+ return;
+ }
+
+ rkh_off = rkh_seq->rx.last[rkh_seq->rx.offsetidx];
+ for (i = 0; i < rkh_seq->rx.num_last; i++) {
+ msg_off = rkh_seq->rx.last[i] - rkh_off;
+ min_off = rkh_seq->rx.last[minidx] - rkh_off;
+ if (msg_off < min_off && i != rkh_seq->rx.offsetidx)
+ minidx = i;
+ }
+ rkh_seq->rx.last[rkh_seq->rx.offsetidx] = msg_seq;
+ rkh_seq->rx.offsetidx = minidx;
+
+ return;
+out:
+ /* RRB_GET_AUTH should never fail here as
+ * wpa_ft_rrb_seq_chk() verified FT_RRB_SEQ presence. */
+ wpa_printf(MSG_ERROR, "FT: %s() failed", __func__);
+}
+
+
+static int wpa_ft_new_seq(struct ft_remote_seq *rkh_seq,
+ struct ft_rrb_seq *f_seq)
+{
+ struct os_reltime now;
+
+ if (os_get_reltime(&now) < 0)
+ return -1;
+
+ if (!rkh_seq->tx.dom) {
+ if (random_get_bytes((u8 *) &rkh_seq->tx.seq,
+ sizeof(rkh_seq->tx.seq))) {
+ wpa_printf(MSG_ERROR,
+ "FT: Failed to get random data for sequence number initialization");
+ rkh_seq->tx.seq = now.usec;
+ }
+ if (random_get_bytes((u8 *) &rkh_seq->tx.dom,
+ sizeof(rkh_seq->tx.dom))) {
+ wpa_printf(MSG_ERROR,
+ "FT: Failed to get random data for sequence number initialization");
+ rkh_seq->tx.dom = now.usec;
+ }
+ rkh_seq->tx.dom |= 1;
+ }
+
+ f_seq->dom = host_to_le32(rkh_seq->tx.dom);
+ f_seq->seq = host_to_le32(rkh_seq->tx.seq);
+ f_seq->ts = host_to_le32(now.sec);
+
+ rkh_seq->tx.seq++;
+
+ return 0;
+}
+
+
struct wpa_ft_pmk_r0_sa {
- struct wpa_ft_pmk_r0_sa *next;
- u8 pmk_r0[PMK_LEN];
+ struct dl_list list;
+ u8 pmk_r0[PMK_LEN_MAX];
+ size_t pmk_r0_len;
u8 pmk_r0_name[WPA_PMK_NAME_LEN];
u8 spa[ETH_ALEN];
int pairwise; /* Pairwise cipher suite, WPA_CIPHER_* */
- /* TODO: expiration, identity, radius_class, EAP type, VLAN ID */
+ struct vlan_description *vlan;
+ os_time_t expiration; /* 0 for no expiration */
+ u8 *identity;
+ size_t identity_len;
+ u8 *radius_cui;
+ size_t radius_cui_len;
+ os_time_t session_timeout; /* 0 for no expiration */
+ /* TODO: radius_class, EAP type */
int pmk_r1_pushed;
};
struct wpa_ft_pmk_r1_sa {
- struct wpa_ft_pmk_r1_sa *next;
- u8 pmk_r1[PMK_LEN];
+ struct dl_list list;
+ u8 pmk_r1[PMK_LEN_MAX];
+ size_t pmk_r1_len;
u8 pmk_r1_name[WPA_PMK_NAME_LEN];
u8 spa[ETH_ALEN];
int pairwise; /* Pairwise cipher suite, WPA_CIPHER_* */
- /* TODO: expiration, identity, radius_class, EAP type, VLAN ID */
+ struct vlan_description *vlan;
+ u8 *identity;
+ size_t identity_len;
+ u8 *radius_cui;
+ size_t radius_cui_len;
+ os_time_t session_timeout; /* 0 for no expiration */
+ /* TODO: radius_class, EAP type */
};
struct wpa_ft_pmk_cache {
- struct wpa_ft_pmk_r0_sa *pmk_r0;
- struct wpa_ft_pmk_r1_sa *pmk_r1;
+ struct dl_list pmk_r0; /* struct wpa_ft_pmk_r0_sa */
+ struct dl_list pmk_r1; /* struct wpa_ft_pmk_r1_sa */
};
+
+static void wpa_ft_expire_pmk_r0(void *eloop_ctx, void *timeout_ctx);
+static void wpa_ft_expire_pmk_r1(void *eloop_ctx, void *timeout_ctx);
+
+
+static void wpa_ft_free_pmk_r0(struct wpa_ft_pmk_r0_sa *r0)
+{
+ if (!r0)
+ return;
+
+ dl_list_del(&r0->list);
+ eloop_cancel_timeout(wpa_ft_expire_pmk_r0, r0, NULL);
+
+ os_memset(r0->pmk_r0, 0, PMK_LEN_MAX);
+ os_free(r0->vlan);
+ os_free(r0->identity);
+ os_free(r0->radius_cui);
+ os_free(r0);
+}
+
+
+static void wpa_ft_expire_pmk_r0(void *eloop_ctx, void *timeout_ctx)
+{
+ struct wpa_ft_pmk_r0_sa *r0 = eloop_ctx;
+ struct os_reltime now;
+ int expires_in;
+ int session_timeout;
+
+ os_get_reltime(&now);
+
+ if (!r0)
+ return;
+
+ expires_in = r0->expiration - now.sec;
+ session_timeout = r0->session_timeout - now.sec;
+ /* conditions to remove from cache:
+ * a) r0->expiration is set and hit
+ * -or-
+ * b) r0->session_timeout is set and hit
+ */
+ if ((!r0->expiration || expires_in > 0) &&
+ (!r0->session_timeout || session_timeout > 0)) {
+ wpa_printf(MSG_ERROR,
+ "FT: %s() called for non-expired entry %p",
+ __func__, r0);
+ eloop_cancel_timeout(wpa_ft_expire_pmk_r0, r0, NULL);
+ if (r0->expiration && expires_in > 0)
+ eloop_register_timeout(expires_in + 1, 0,
+ wpa_ft_expire_pmk_r0, r0, NULL);
+ if (r0->session_timeout && session_timeout > 0)
+ eloop_register_timeout(session_timeout + 1, 0,
+ wpa_ft_expire_pmk_r0, r0, NULL);
+ return;
+ }
+
+ wpa_ft_free_pmk_r0(r0);
+}
+
+
+static void wpa_ft_free_pmk_r1(struct wpa_ft_pmk_r1_sa *r1)
+{
+ if (!r1)
+ return;
+
+ dl_list_del(&r1->list);
+ eloop_cancel_timeout(wpa_ft_expire_pmk_r1, r1, NULL);
+
+ os_memset(r1->pmk_r1, 0, PMK_LEN_MAX);
+ os_free(r1->vlan);
+ os_free(r1->identity);
+ os_free(r1->radius_cui);
+ os_free(r1);
+}
+
+
+static void wpa_ft_expire_pmk_r1(void *eloop_ctx, void *timeout_ctx)
+{
+ struct wpa_ft_pmk_r1_sa *r1 = eloop_ctx;
+
+ wpa_ft_free_pmk_r1(r1);
+}
+
+
struct wpa_ft_pmk_cache * wpa_ft_pmk_cache_init(void)
{
struct wpa_ft_pmk_cache *cache;
cache = os_zalloc(sizeof(*cache));
+ if (cache) {
+ dl_list_init(&cache->pmk_r0);
+ dl_list_init(&cache->pmk_r1);
+ }
return cache;
}
@@ -183,21 +1306,13 @@ void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache)
struct wpa_ft_pmk_r0_sa *r0, *r0prev;
struct wpa_ft_pmk_r1_sa *r1, *r1prev;
- r0 = cache->pmk_r0;
- while (r0) {
- r0prev = r0;
- r0 = r0->next;
- os_memset(r0prev->pmk_r0, 0, PMK_LEN);
- os_free(r0prev);
- }
+ dl_list_for_each_safe(r0, r0prev, &cache->pmk_r0,
+ struct wpa_ft_pmk_r0_sa, list)
+ wpa_ft_free_pmk_r0(r0);
- r1 = cache->pmk_r1;
- while (r1) {
- r1prev = r1;
- r1 = r1->next;
- os_memset(r1prev->pmk_r1, 0, PMK_LEN);
- os_free(r1prev);
- }
+ dl_list_for_each_safe(r1, r1prev, &cache->pmk_r1,
+ struct wpa_ft_pmk_r1_sa, list)
+ wpa_ft_free_pmk_r1(r1);
os_free(cache);
}
@@ -205,24 +1320,63 @@ void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache)
static int wpa_ft_store_pmk_r0(struct wpa_authenticator *wpa_auth,
const u8 *spa, const u8 *pmk_r0,
- const u8 *pmk_r0_name, int pairwise)
+ size_t pmk_r0_len,
+ const u8 *pmk_r0_name, int pairwise,
+ const struct vlan_description *vlan,
+ int expires_in, int session_timeout,
+ const u8 *identity, size_t identity_len,
+ const u8 *radius_cui, size_t radius_cui_len)
{
struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache;
struct wpa_ft_pmk_r0_sa *r0;
+ struct os_reltime now;
- /* TODO: add expiration and limit on number of entries in cache */
+ /* TODO: add limit on number of entries in cache */
+ os_get_reltime(&now);
r0 = os_zalloc(sizeof(*r0));
if (r0 == NULL)
return -1;
- os_memcpy(r0->pmk_r0, pmk_r0, PMK_LEN);
+ os_memcpy(r0->pmk_r0, pmk_r0, pmk_r0_len);
+ r0->pmk_r0_len = pmk_r0_len;
os_memcpy(r0->pmk_r0_name, pmk_r0_name, WPA_PMK_NAME_LEN);
os_memcpy(r0->spa, spa, ETH_ALEN);
r0->pairwise = pairwise;
+ if (expires_in > 0)
+ r0->expiration = now.sec + expires_in;
+ if (vlan && vlan->notempty) {
+ r0->vlan = os_zalloc(sizeof(*vlan));
+ if (!r0->vlan) {
+ bin_clear_free(r0, sizeof(*r0));
+ return -1;
+ }
+ *r0->vlan = *vlan;
+ }
+ if (identity) {
+ r0->identity = os_malloc(identity_len);
+ if (r0->identity) {
+ os_memcpy(r0->identity, identity, identity_len);
+ r0->identity_len = identity_len;
+ }
+ }
+ if (radius_cui) {
+ r0->radius_cui = os_malloc(radius_cui_len);
+ if (r0->radius_cui) {
+ os_memcpy(r0->radius_cui, radius_cui, radius_cui_len);
+ r0->radius_cui_len = radius_cui_len;
+ }
+ }
+ if (session_timeout > 0)
+ r0->session_timeout = now.sec + session_timeout;
- r0->next = cache->pmk_r0;
- cache->pmk_r0 = r0;
+ dl_list_add(&cache->pmk_r0, &r0->list);
+ if (expires_in > 0)
+ eloop_register_timeout(expires_in + 1, 0, wpa_ft_expire_pmk_r0,
+ r0, NULL);
+ if (session_timeout > 0)
+ eloop_register_timeout(session_timeout + 1, 0,
+ wpa_ft_expire_pmk_r0, r0, NULL);
return 0;
}
@@ -230,49 +1384,89 @@ static int wpa_ft_store_pmk_r0(struct wpa_authenticator *wpa_auth,
static int wpa_ft_fetch_pmk_r0(struct wpa_authenticator *wpa_auth,
const u8 *spa, const u8 *pmk_r0_name,
- u8 *pmk_r0, int *pairwise)
+ const struct wpa_ft_pmk_r0_sa **r0_out)
{
struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache;
struct wpa_ft_pmk_r0_sa *r0;
+ struct os_reltime now;
- r0 = cache->pmk_r0;
- while (r0) {
+ os_get_reltime(&now);
+ dl_list_for_each(r0, &cache->pmk_r0, struct wpa_ft_pmk_r0_sa, list) {
if (os_memcmp(r0->spa, spa, ETH_ALEN) == 0 &&
os_memcmp_const(r0->pmk_r0_name, pmk_r0_name,
WPA_PMK_NAME_LEN) == 0) {
- os_memcpy(pmk_r0, r0->pmk_r0, PMK_LEN);
- if (pairwise)
- *pairwise = r0->pairwise;
+ *r0_out = r0;
return 0;
}
-
- r0 = r0->next;
}
+ *r0_out = NULL;
return -1;
}
static int wpa_ft_store_pmk_r1(struct wpa_authenticator *wpa_auth,
const u8 *spa, const u8 *pmk_r1,
- const u8 *pmk_r1_name, int pairwise)
+ size_t pmk_r1_len,
+ const u8 *pmk_r1_name, int pairwise,
+ const struct vlan_description *vlan,
+ int expires_in, int session_timeout,
+ const u8 *identity, size_t identity_len,
+ const u8 *radius_cui, size_t radius_cui_len)
{
struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache;
+ int max_expires_in = wpa_auth->conf.r1_max_key_lifetime;
struct wpa_ft_pmk_r1_sa *r1;
+ struct os_reltime now;
- /* TODO: add expiration and limit on number of entries in cache */
+ /* TODO: limit on number of entries in cache */
+ os_get_reltime(&now);
+
+ if (max_expires_in && (max_expires_in < expires_in || expires_in == 0))
+ expires_in = max_expires_in;
r1 = os_zalloc(sizeof(*r1));
if (r1 == NULL)
return -1;
- os_memcpy(r1->pmk_r1, pmk_r1, PMK_LEN);
+ os_memcpy(r1->pmk_r1, pmk_r1, pmk_r1_len);
+ r1->pmk_r1_len = pmk_r1_len;
os_memcpy(r1->pmk_r1_name, pmk_r1_name, WPA_PMK_NAME_LEN);
os_memcpy(r1->spa, spa, ETH_ALEN);
r1->pairwise = pairwise;
+ if (vlan && vlan->notempty) {
+ r1->vlan = os_zalloc(sizeof(*vlan));
+ if (!r1->vlan) {
+ bin_clear_free(r1, sizeof(*r1));
+ return -1;
+ }
+ *r1->vlan = *vlan;
+ }
+ if (identity) {
+ r1->identity = os_malloc(identity_len);
+ if (r1->identity) {
+ os_memcpy(r1->identity, identity, identity_len);
+ r1->identity_len = identity_len;
+ }
+ }
+ if (radius_cui) {
+ r1->radius_cui = os_malloc(radius_cui_len);
+ if (r1->radius_cui) {
+ os_memcpy(r1->radius_cui, radius_cui, radius_cui_len);
+ r1->radius_cui_len = radius_cui_len;
+ }
+ }
+ if (session_timeout > 0)
+ r1->session_timeout = now.sec + session_timeout;
+
+ dl_list_add(&cache->pmk_r1, &r1->list);
- r1->next = cache->pmk_r1;
- cache->pmk_r1 = r1;
+ if (expires_in > 0)
+ eloop_register_timeout(expires_in + 1, 0, wpa_ft_expire_pmk_r1,
+ r1, NULL);
+ if (session_timeout > 0)
+ eloop_register_timeout(session_timeout + 1, 0,
+ wpa_ft_expire_pmk_r1, r1, NULL);
return 0;
}
@@ -280,94 +1474,615 @@ static int wpa_ft_store_pmk_r1(struct wpa_authenticator *wpa_auth,
static int wpa_ft_fetch_pmk_r1(struct wpa_authenticator *wpa_auth,
const u8 *spa, const u8 *pmk_r1_name,
- u8 *pmk_r1, int *pairwise)
+ u8 *pmk_r1, size_t *pmk_r1_len, int *pairwise,
+ struct vlan_description *vlan,
+ const u8 **identity, size_t *identity_len,
+ const u8 **radius_cui, size_t *radius_cui_len,
+ int *session_timeout)
{
struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache;
struct wpa_ft_pmk_r1_sa *r1;
+ struct os_reltime now;
- r1 = cache->pmk_r1;
- while (r1) {
+ os_get_reltime(&now);
+
+ dl_list_for_each(r1, &cache->pmk_r1, struct wpa_ft_pmk_r1_sa, list) {
if (os_memcmp(r1->spa, spa, ETH_ALEN) == 0 &&
os_memcmp_const(r1->pmk_r1_name, pmk_r1_name,
WPA_PMK_NAME_LEN) == 0) {
- os_memcpy(pmk_r1, r1->pmk_r1, PMK_LEN);
+ os_memcpy(pmk_r1, r1->pmk_r1, r1->pmk_r1_len);
+ *pmk_r1_len = r1->pmk_r1_len;
if (pairwise)
*pairwise = r1->pairwise;
+ if (vlan && r1->vlan)
+ *vlan = *r1->vlan;
+ if (vlan && !r1->vlan)
+ os_memset(vlan, 0, sizeof(*vlan));
+ if (identity && identity_len) {
+ *identity = r1->identity;
+ *identity_len = r1->identity_len;
+ }
+ if (radius_cui && radius_cui_len) {
+ *radius_cui = r1->radius_cui;
+ *radius_cui_len = r1->radius_cui_len;
+ }
+ if (session_timeout && r1->session_timeout > now.sec)
+ *session_timeout = r1->session_timeout -
+ now.sec;
+ else if (session_timeout && r1->session_timeout)
+ *session_timeout = 1;
+ else if (session_timeout)
+ *session_timeout = 0;
return 0;
}
-
- r1 = r1->next;
}
return -1;
}
-static int wpa_ft_pull_pmk_r1(struct wpa_state_machine *sm,
- const u8 *ies, size_t ies_len,
- const u8 *pmk_r0_name)
+static int wpa_ft_rrb_init_r0kh_seq(struct ft_remote_r0kh *r0kh)
+{
+ if (r0kh->seq)
+ return 0;
+
+ r0kh->seq = os_zalloc(sizeof(*r0kh->seq));
+ if (!r0kh->seq) {
+ wpa_printf(MSG_DEBUG, "FT: Failed to allocate r0kh->seq");
+ return -1;
+ }
+
+ dl_list_init(&r0kh->seq->rx.queue);
+
+ return 0;
+}
+
+
+static void wpa_ft_rrb_lookup_r0kh(struct wpa_authenticator *wpa_auth,
+ const u8 *f_r0kh_id, size_t f_r0kh_id_len,
+ struct ft_remote_r0kh **r0kh_out,
+ struct ft_remote_r0kh **r0kh_wildcard)
{
struct ft_remote_r0kh *r0kh;
- struct ft_r0kh_r1kh_pull_frame frame, f;
- r0kh = sm->wpa_auth->conf.r0kh_list;
- while (r0kh) {
- if (r0kh->id_len == sm->r0kh_id_len &&
- os_memcmp_const(r0kh->id, sm->r0kh_id, sm->r0kh_id_len) ==
- 0)
+ *r0kh_wildcard = NULL;
+ *r0kh_out = NULL;
+
+ if (wpa_auth->conf.r0kh_list)
+ r0kh = *wpa_auth->conf.r0kh_list;
+ else
+ r0kh = NULL;
+ for (; r0kh; r0kh = r0kh->next) {
+ if (r0kh->id_len == 1 && r0kh->id[0] == '*')
+ *r0kh_wildcard = r0kh;
+ if (f_r0kh_id && r0kh->id_len == f_r0kh_id_len &&
+ os_memcmp_const(f_r0kh_id, r0kh->id, f_r0kh_id_len) == 0)
+ *r0kh_out = r0kh;
+ }
+
+ if (!*r0kh_out && !*r0kh_wildcard)
+ wpa_printf(MSG_DEBUG, "FT: No matching R0KH found");
+
+ if (*r0kh_out && wpa_ft_rrb_init_r0kh_seq(*r0kh_out) < 0)
+ *r0kh_out = NULL;
+}
+
+
+static int wpa_ft_rrb_init_r1kh_seq(struct ft_remote_r1kh *r1kh)
+{
+ if (r1kh->seq)
+ return 0;
+
+ r1kh->seq = os_zalloc(sizeof(*r1kh->seq));
+ if (!r1kh->seq) {
+ wpa_printf(MSG_DEBUG, "FT: Failed to allocate r1kh->seq");
+ return -1;
+ }
+
+ dl_list_init(&r1kh->seq->rx.queue);
+
+ return 0;
+}
+
+
+static void wpa_ft_rrb_lookup_r1kh(struct wpa_authenticator *wpa_auth,
+ const u8 *f_r1kh_id,
+ struct ft_remote_r1kh **r1kh_out,
+ struct ft_remote_r1kh **r1kh_wildcard)
+{
+ struct ft_remote_r1kh *r1kh;
+
+ *r1kh_wildcard = NULL;
+ *r1kh_out = NULL;
+
+ if (wpa_auth->conf.r1kh_list)
+ r1kh = *wpa_auth->conf.r1kh_list;
+ else
+ r1kh = NULL;
+ for (; r1kh; r1kh = r1kh->next) {
+ if (is_zero_ether_addr(r1kh->addr) &&
+ is_zero_ether_addr(r1kh->id))
+ *r1kh_wildcard = r1kh;
+ if (f_r1kh_id &&
+ os_memcmp_const(r1kh->id, f_r1kh_id, FT_R1KH_ID_LEN) == 0)
+ *r1kh_out = r1kh;
+ }
+
+ if (!*r1kh_out && !*r1kh_wildcard)
+ wpa_printf(MSG_DEBUG, "FT: No matching R1KH found");
+
+ if (*r1kh_out && wpa_ft_rrb_init_r1kh_seq(*r1kh_out) < 0)
+ *r1kh_out = NULL;
+}
+
+
+static int wpa_ft_rrb_check_r0kh(struct wpa_authenticator *wpa_auth,
+ const u8 *f_r0kh_id, size_t f_r0kh_id_len)
+{
+ if (f_r0kh_id_len != wpa_auth->conf.r0_key_holder_len ||
+ os_memcmp_const(f_r0kh_id, wpa_auth->conf.r0_key_holder,
+ f_r0kh_id_len) != 0)
+ return -1;
+
+ return 0;
+}
+
+
+static int wpa_ft_rrb_check_r1kh(struct wpa_authenticator *wpa_auth,
+ const u8 *f_r1kh_id)
+{
+ if (os_memcmp_const(f_r1kh_id, wpa_auth->conf.r1_key_holder,
+ FT_R1KH_ID_LEN) != 0)
+ return -1;
+
+ return 0;
+}
+
+
+static void wpa_ft_rrb_del_r0kh(void *eloop_ctx, void *timeout_ctx)
+{
+ struct wpa_authenticator *wpa_auth = eloop_ctx;
+ struct ft_remote_r0kh *r0kh, *prev = NULL;
+
+ if (!wpa_auth->conf.r0kh_list)
+ return;
+
+ for (r0kh = *wpa_auth->conf.r0kh_list; r0kh; r0kh = r0kh->next) {
+ if (r0kh == timeout_ctx)
break;
- r0kh = r0kh->next;
+ prev = r0kh;
+ }
+ if (!r0kh)
+ return;
+ if (prev)
+ prev->next = r0kh->next;
+ else
+ *wpa_auth->conf.r0kh_list = r0kh->next;
+ if (r0kh->seq)
+ wpa_ft_rrb_seq_flush(wpa_auth, r0kh->seq, 0);
+ os_free(r0kh->seq);
+ os_free(r0kh);
+}
+
+
+static void wpa_ft_rrb_r0kh_replenish(struct wpa_authenticator *wpa_auth,
+ struct ft_remote_r0kh *r0kh, int timeout)
+{
+ if (timeout > 0)
+ eloop_replenish_timeout(timeout, 0, wpa_ft_rrb_del_r0kh,
+ wpa_auth, r0kh);
+}
+
+
+static void wpa_ft_rrb_r0kh_timeout(struct wpa_authenticator *wpa_auth,
+ struct ft_remote_r0kh *r0kh, int timeout)
+{
+ eloop_cancel_timeout(wpa_ft_rrb_del_r0kh, wpa_auth, r0kh);
+
+ if (timeout > 0)
+ eloop_register_timeout(timeout, 0, wpa_ft_rrb_del_r0kh,
+ wpa_auth, r0kh);
+}
+
+
+static struct ft_remote_r0kh *
+wpa_ft_rrb_add_r0kh(struct wpa_authenticator *wpa_auth,
+ struct ft_remote_r0kh *r0kh_wildcard,
+ const u8 *src_addr, const u8 *r0kh_id, size_t id_len,
+ int timeout)
+{
+ struct ft_remote_r0kh *r0kh;
+
+ if (!wpa_auth->conf.r0kh_list)
+ return NULL;
+
+ r0kh = os_zalloc(sizeof(*r0kh));
+ if (!r0kh)
+ return NULL;
+
+ if (src_addr)
+ os_memcpy(r0kh->addr, src_addr, sizeof(r0kh->addr));
+
+ if (id_len > FT_R0KH_ID_MAX_LEN)
+ id_len = FT_R0KH_ID_MAX_LEN;
+ os_memcpy(r0kh->id, r0kh_id, id_len);
+ r0kh->id_len = id_len;
+
+ os_memcpy(r0kh->key, r0kh_wildcard->key, sizeof(r0kh->key));
+
+ r0kh->next = *wpa_auth->conf.r0kh_list;
+ *wpa_auth->conf.r0kh_list = r0kh;
+
+ if (timeout > 0)
+ eloop_register_timeout(timeout, 0, wpa_ft_rrb_del_r0kh,
+ wpa_auth, r0kh);
+
+ if (wpa_ft_rrb_init_r0kh_seq(r0kh) < 0)
+ return NULL;
+
+ return r0kh;
+}
+
+
+static void wpa_ft_rrb_del_r1kh(void *eloop_ctx, void *timeout_ctx)
+{
+ struct wpa_authenticator *wpa_auth = eloop_ctx;
+ struct ft_remote_r1kh *r1kh, *prev = NULL;
+
+ if (!wpa_auth->conf.r1kh_list)
+ return;
+
+ for (r1kh = *wpa_auth->conf.r1kh_list; r1kh; r1kh = r1kh->next) {
+ if (r1kh == timeout_ctx)
+ break;
+ prev = r1kh;
+ }
+ if (!r1kh)
+ return;
+ if (prev)
+ prev->next = r1kh->next;
+ else
+ *wpa_auth->conf.r1kh_list = r1kh->next;
+ if (r1kh->seq)
+ wpa_ft_rrb_seq_flush(wpa_auth, r1kh->seq, 0);
+ os_free(r1kh->seq);
+ os_free(r1kh);
+}
+
+
+static void wpa_ft_rrb_r1kh_replenish(struct wpa_authenticator *wpa_auth,
+ struct ft_remote_r1kh *r1kh, int timeout)
+{
+ if (timeout > 0)
+ eloop_replenish_timeout(timeout, 0, wpa_ft_rrb_del_r1kh,
+ wpa_auth, r1kh);
+}
+
+
+static struct ft_remote_r1kh *
+wpa_ft_rrb_add_r1kh(struct wpa_authenticator *wpa_auth,
+ struct ft_remote_r1kh *r1kh_wildcard,
+ const u8 *src_addr, const u8 *r1kh_id, int timeout)
+{
+ struct ft_remote_r1kh *r1kh;
+
+ if (!wpa_auth->conf.r1kh_list)
+ return NULL;
+
+ r1kh = os_zalloc(sizeof(*r1kh));
+ if (!r1kh)
+ return NULL;
+
+ os_memcpy(r1kh->addr, src_addr, sizeof(r1kh->addr));
+ os_memcpy(r1kh->id, r1kh_id, sizeof(r1kh->id));
+ os_memcpy(r1kh->key, r1kh_wildcard->key, sizeof(r1kh->key));
+ r1kh->next = *wpa_auth->conf.r1kh_list;
+ *wpa_auth->conf.r1kh_list = r1kh;
+
+ if (timeout > 0)
+ eloop_register_timeout(timeout, 0, wpa_ft_rrb_del_r1kh,
+ wpa_auth, r1kh);
+
+ if (wpa_ft_rrb_init_r1kh_seq(r1kh) < 0)
+ return NULL;
+
+ return r1kh;
+}
+
+
+void wpa_ft_sta_deinit(struct wpa_state_machine *sm)
+{
+ eloop_cancel_timeout(wpa_ft_expire_pull, sm, NULL);
+}
+
+
+static void wpa_ft_deinit_seq(struct wpa_authenticator *wpa_auth)
+{
+ struct ft_remote_r0kh *r0kh;
+ struct ft_remote_r1kh *r1kh;
+
+ eloop_cancel_timeout(wpa_ft_rrb_seq_timeout, wpa_auth, ELOOP_ALL_CTX);
+
+ if (wpa_auth->conf.r0kh_list)
+ r0kh = *wpa_auth->conf.r0kh_list;
+ else
+ r0kh = NULL;
+ for (; r0kh; r0kh = r0kh->next) {
+ if (!r0kh->seq)
+ continue;
+ wpa_ft_rrb_seq_flush(wpa_auth, r0kh->seq, 0);
+ os_free(r0kh->seq);
+ r0kh->seq = NULL;
+ }
+
+ if (wpa_auth->conf.r1kh_list)
+ r1kh = *wpa_auth->conf.r1kh_list;
+ else
+ r1kh = NULL;
+ for (; r1kh; r1kh = r1kh->next) {
+ if (!r1kh->seq)
+ continue;
+ wpa_ft_rrb_seq_flush(wpa_auth, r1kh->seq, 0);
+ os_free(r1kh->seq);
+ r1kh->seq = NULL;
+ }
+}
+
+
+static void wpa_ft_deinit_rkh_tmp(struct wpa_authenticator *wpa_auth)
+{
+ struct ft_remote_r0kh *r0kh, *r0kh_next, *r0kh_prev = NULL;
+ struct ft_remote_r1kh *r1kh, *r1kh_next, *r1kh_prev = NULL;
+
+ if (wpa_auth->conf.r0kh_list)
+ r0kh = *wpa_auth->conf.r0kh_list;
+ else
+ r0kh = NULL;
+ while (r0kh) {
+ r0kh_next = r0kh->next;
+ if (eloop_cancel_timeout(wpa_ft_rrb_del_r0kh, wpa_auth,
+ r0kh) > 0) {
+ if (r0kh_prev)
+ r0kh_prev->next = r0kh_next;
+ else
+ *wpa_auth->conf.r0kh_list = r0kh_next;
+ os_free(r0kh);
+ } else {
+ r0kh_prev = r0kh;
+ }
+ r0kh = r0kh_next;
+ }
+
+ if (wpa_auth->conf.r1kh_list)
+ r1kh = *wpa_auth->conf.r1kh_list;
+ else
+ r1kh = NULL;
+ while (r1kh) {
+ r1kh_next = r1kh->next;
+ if (eloop_cancel_timeout(wpa_ft_rrb_del_r1kh, wpa_auth,
+ r1kh) > 0) {
+ if (r1kh_prev)
+ r1kh_prev->next = r1kh_next;
+ else
+ *wpa_auth->conf.r1kh_list = r1kh_next;
+ os_free(r1kh);
+ } else {
+ r1kh_prev = r1kh;
+ }
+ r1kh = r1kh_next;
+ }
+}
+
+
+void wpa_ft_deinit(struct wpa_authenticator *wpa_auth)
+{
+ wpa_ft_deinit_seq(wpa_auth);
+ wpa_ft_deinit_rkh_tmp(wpa_auth);
+}
+
+
+static void wpa_ft_block_r0kh(struct wpa_authenticator *wpa_auth,
+ const u8 *f_r0kh_id, size_t f_r0kh_id_len)
+{
+ struct ft_remote_r0kh *r0kh, *r0kh_wildcard;
+
+ if (!wpa_auth->conf.rkh_neg_timeout)
+ return;
+
+ wpa_ft_rrb_lookup_r0kh(wpa_auth, f_r0kh_id, f_r0kh_id_len,
+ &r0kh, &r0kh_wildcard);
+
+ if (!r0kh_wildcard) {
+ /* r0kh removed after neg_timeout and might need re-adding */
+ return;
+ }
+
+ wpa_hexdump(MSG_DEBUG, "FT: Blacklist R0KH-ID",
+ f_r0kh_id, f_r0kh_id_len);
+
+ if (r0kh) {
+ wpa_ft_rrb_r0kh_timeout(wpa_auth, r0kh,
+ wpa_auth->conf.rkh_neg_timeout);
+ os_memset(r0kh->addr, 0, ETH_ALEN);
+ } else
+ wpa_ft_rrb_add_r0kh(wpa_auth, r0kh_wildcard, NULL, f_r0kh_id,
+ f_r0kh_id_len,
+ wpa_auth->conf.rkh_neg_timeout);
+}
+
+
+static void wpa_ft_expire_pull(void *eloop_ctx, void *timeout_ctx)
+{
+ struct wpa_state_machine *sm = eloop_ctx;
+
+ wpa_printf(MSG_DEBUG, "FT: Timeout pending pull request for " MACSTR,
+ MAC2STR(sm->addr));
+ if (sm->ft_pending_pull_left_retries <= 0)
+ wpa_ft_block_r0kh(sm->wpa_auth, sm->r0kh_id, sm->r0kh_id_len);
+
+ /* cancel multiple timeouts */
+ eloop_cancel_timeout(wpa_ft_expire_pull, sm, NULL);
+ ft_finish_pull(sm);
+}
+
+
+static int wpa_ft_pull_pmk_r1(struct wpa_state_machine *sm,
+ const u8 *ies, size_t ies_len,
+ const u8 *pmk_r0_name)
+{
+ struct ft_remote_r0kh *r0kh, *r0kh_wildcard;
+ u8 *packet = NULL;
+ const u8 *key, *f_r1kh_id = sm->wpa_auth->conf.r1_key_holder;
+ size_t packet_len, key_len;
+ struct ft_rrb_seq f_seq;
+ int tsecs, tusecs, first;
+ struct wpabuf *ft_pending_req_ies;
+ int r0kh_timeout;
+ struct tlv_list req_enc[] = {
+ { .type = FT_RRB_PMK_R0_NAME, .len = WPA_PMK_NAME_LEN,
+ .data = pmk_r0_name },
+ { .type = FT_RRB_S1KH_ID, .len = ETH_ALEN,
+ .data = sm->addr },
+ { .type = FT_RRB_LAST_EMPTY, .len = 0, .data = NULL },
+ };
+ struct tlv_list req_auth[] = {
+ { .type = FT_RRB_NONCE, .len = FT_RRB_NONCE_LEN,
+ .data = sm->ft_pending_pull_nonce },
+ { .type = FT_RRB_SEQ, .len = sizeof(f_seq),
+ .data = (u8 *) &f_seq },
+ { .type = FT_RRB_R0KH_ID, .len = sm->r0kh_id_len,
+ .data = sm->r0kh_id },
+ { .type = FT_RRB_R1KH_ID, .len = FT_R1KH_ID_LEN,
+ .data = f_r1kh_id },
+ { .type = FT_RRB_LAST_EMPTY, .len = 0, .data = NULL },
+ };
+
+ if (sm->ft_pending_pull_left_retries <= 0)
+ return -1;
+ first = sm->ft_pending_pull_left_retries ==
+ sm->wpa_auth->conf.rkh_pull_retries;
+ sm->ft_pending_pull_left_retries--;
+
+ wpa_ft_rrb_lookup_r0kh(sm->wpa_auth, sm->r0kh_id, sm->r0kh_id_len,
+ &r0kh, &r0kh_wildcard);
+
+ /* Keep r0kh sufficiently long in the list for seq num check */
+ r0kh_timeout = sm->wpa_auth->conf.rkh_pull_timeout / 1000 +
+ 1 + ftRRBseqTimeout;
+ if (r0kh) {
+ wpa_ft_rrb_r0kh_replenish(sm->wpa_auth, r0kh, r0kh_timeout);
+ } else if (r0kh_wildcard) {
+ wpa_printf(MSG_DEBUG, "FT: Using wildcard R0KH-ID");
+ /* r0kh->addr: updated by SEQ_RESP and wpa_ft_expire_pull */
+ r0kh = wpa_ft_rrb_add_r0kh(sm->wpa_auth, r0kh_wildcard,
+ r0kh_wildcard->addr,
+ sm->r0kh_id, sm->r0kh_id_len,
+ r0kh_timeout);
}
if (r0kh == NULL) {
wpa_hexdump(MSG_DEBUG, "FT: Did not find R0KH-ID",
sm->r0kh_id, sm->r0kh_id_len);
return -1;
}
+ if (is_zero_ether_addr(r0kh->addr)) {
+ wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID is blacklisted",
+ sm->r0kh_id, sm->r0kh_id_len);
+ return -1;
+ }
+ if (os_memcmp(r0kh->addr, sm->wpa_auth->addr, ETH_ALEN) == 0) {
+ wpa_printf(MSG_DEBUG,
+ "FT: R0KH-ID points to self - no matching key available");
+ return -1;
+ }
+
+ key = r0kh->key;
+ key_len = sizeof(r0kh->key);
wpa_printf(MSG_DEBUG, "FT: Send PMK-R1 pull request to remote R0KH "
"address " MACSTR, MAC2STR(r0kh->addr));
- os_memset(&frame, 0, sizeof(frame));
- frame.frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB;
- frame.packet_type = FT_PACKET_R0KH_R1KH_PULL;
- frame.data_length = host_to_le16(FT_R0KH_R1KH_PULL_DATA_LEN);
- os_memcpy(frame.ap_address, sm->wpa_auth->addr, ETH_ALEN);
+ if (r0kh->seq->rx.num_last == 0) {
+ /* A sequence request will be sent out anyway when pull
+ * response is received. Send it out now to avoid one RTT. */
+ wpa_ft_rrb_seq_req(sm->wpa_auth, r0kh->seq, r0kh->addr,
+ r0kh->id, r0kh->id_len, f_r1kh_id, key,
+ key_len, NULL, 0, NULL, 0, NULL);
+ }
- /* aes_wrap() does not support inplace encryption, so use a temporary
- * buffer for the data. */
- if (random_get_bytes(f.nonce, FT_R0KH_R1KH_PULL_NONCE_LEN)) {
+ if (first &&
+ random_get_bytes(sm->ft_pending_pull_nonce, FT_RRB_NONCE_LEN) < 0) {
wpa_printf(MSG_DEBUG, "FT: Failed to get random data for "
"nonce");
return -1;
}
- os_memcpy(sm->ft_pending_pull_nonce, f.nonce,
- FT_R0KH_R1KH_PULL_NONCE_LEN);
- os_memcpy(f.pmk_r0_name, pmk_r0_name, WPA_PMK_NAME_LEN);
- os_memcpy(f.r1kh_id, sm->wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN);
- os_memcpy(f.s1kh_id, sm->addr, ETH_ALEN);
- os_memset(f.pad, 0, sizeof(f.pad));
- if (aes_wrap(r0kh->key, sizeof(r0kh->key),
- (FT_R0KH_R1KH_PULL_DATA_LEN + 7) / 8,
- f.nonce, frame.nonce) < 0)
+ if (wpa_ft_new_seq(r0kh->seq, &f_seq) < 0) {
+ wpa_printf(MSG_DEBUG, "FT: Failed to get seq num");
+ return -1;
+ }
+
+ if (wpa_ft_rrb_build(key, key_len, req_enc, NULL, req_auth, NULL,
+ sm->wpa_auth->addr, FT_PACKET_R0KH_R1KH_PULL,
+ &packet, &packet_len) < 0)
return -1;
+ ft_pending_req_ies = wpabuf_alloc_copy(ies, ies_len);
wpabuf_free(sm->ft_pending_req_ies);
- sm->ft_pending_req_ies = wpabuf_alloc_copy(ies, ies_len);
- if (sm->ft_pending_req_ies == NULL)
+ sm->ft_pending_req_ies = ft_pending_req_ies;
+ if (!sm->ft_pending_req_ies) {
+ os_free(packet);
return -1;
+ }
+
+ tsecs = sm->wpa_auth->conf.rkh_pull_timeout / 1000;
+ tusecs = (sm->wpa_auth->conf.rkh_pull_timeout % 1000) * 1000;
+ eloop_register_timeout(tsecs, tusecs, wpa_ft_expire_pull, sm, NULL);
+
+ wpa_ft_rrb_oui_send(sm->wpa_auth, r0kh->addr, FT_PACKET_R0KH_R1KH_PULL,
+ packet, packet_len);
- wpa_ft_rrb_send(sm->wpa_auth, r0kh->addr, (u8 *) &frame, sizeof(frame));
+ os_free(packet);
return 0;
}
-int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk,
- struct wpa_ptk *ptk)
+int wpa_ft_store_pmk_fils(struct wpa_state_machine *sm,
+ const u8 *pmk_r0, const u8 *pmk_r0_name)
{
- u8 pmk_r0[PMK_LEN], pmk_r0_name[WPA_PMK_NAME_LEN];
- u8 pmk_r1[PMK_LEN];
+ int expires_in = sm->wpa_auth->conf.r0_key_lifetime;
+ struct vlan_description vlan;
+ const u8 *identity, *radius_cui;
+ size_t identity_len, radius_cui_len;
+ int session_timeout;
+ size_t pmk_r0_len = wpa_key_mgmt_sha384(sm->wpa_key_mgmt) ?
+ SHA384_MAC_LEN : PMK_LEN;
+
+ if (wpa_ft_get_vlan(sm->wpa_auth, sm->addr, &vlan) < 0) {
+ wpa_printf(MSG_DEBUG, "FT: vlan not available for STA " MACSTR,
+ MAC2STR(sm->addr));
+ return -1;
+ }
+
+ identity_len = wpa_ft_get_identity(sm->wpa_auth, sm->addr, &identity);
+ radius_cui_len = wpa_ft_get_radius_cui(sm->wpa_auth, sm->addr,
+ &radius_cui);
+ session_timeout = wpa_ft_get_session_timeout(sm->wpa_auth, sm->addr);
+
+ return wpa_ft_store_pmk_r0(sm->wpa_auth, sm->addr, pmk_r0, pmk_r0_len,
+ pmk_r0_name, sm->pairwise, &vlan, expires_in,
+ session_timeout, identity, identity_len,
+ radius_cui, radius_cui_len);
+}
+
+
+int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk)
+{
+ u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN];
+ size_t pmk_r0_len = wpa_key_mgmt_sha384(sm->wpa_key_mgmt) ?
+ SHA384_MAC_LEN : PMK_LEN;
+ size_t pmk_r1_len = pmk_r0_len;
+ u8 pmk_r1[PMK_LEN_MAX];
u8 ptk_name[WPA_PMK_NAME_LEN];
const u8 *mdid = sm->wpa_auth->conf.mobility_domain;
const u8 *r0kh = sm->wpa_auth->conf.r0_key_holder;
@@ -375,6 +2090,12 @@ int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk,
const u8 *r1kh = sm->wpa_auth->conf.r1_key_holder;
const u8 *ssid = sm->wpa_auth->conf.ssid;
size_t ssid_len = sm->wpa_auth->conf.ssid_len;
+ int psk_local = sm->wpa_auth->conf.ft_psk_generate_local;
+ int expires_in = sm->wpa_auth->conf.r0_key_lifetime;
+ struct vlan_description vlan;
+ const u8 *identity, *radius_cui;
+ size_t identity_len, radius_cui_len;
+ int session_timeout;
if (sm->xxkey_len == 0) {
wpa_printf(MSG_DEBUG, "FT: XXKey not available for key "
@@ -382,23 +2103,45 @@ int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk,
return -1;
}
- wpa_derive_pmk_r0(sm->xxkey, sm->xxkey_len, ssid, ssid_len, mdid,
- r0kh, r0kh_len, sm->addr, pmk_r0, pmk_r0_name);
- wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", pmk_r0, PMK_LEN);
- wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name", pmk_r0_name, WPA_PMK_NAME_LEN);
- wpa_ft_store_pmk_r0(sm->wpa_auth, sm->addr, pmk_r0, pmk_r0_name,
- sm->pairwise);
+ if (wpa_ft_get_vlan(sm->wpa_auth, sm->addr, &vlan) < 0) {
+ wpa_printf(MSG_DEBUG, "FT: vlan not available for STA " MACSTR,
+ MAC2STR(sm->addr));
+ return -1;
+ }
+
+ identity_len = wpa_ft_get_identity(sm->wpa_auth, sm->addr, &identity);
+ radius_cui_len = wpa_ft_get_radius_cui(sm->wpa_auth, sm->addr,
+ &radius_cui);
+ session_timeout = wpa_ft_get_session_timeout(sm->wpa_auth, sm->addr);
- wpa_derive_pmk_r1(pmk_r0, pmk_r0_name, r1kh, sm->addr,
- pmk_r1, sm->pmk_r1_name);
- wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", pmk_r1, PMK_LEN);
+ if (wpa_derive_pmk_r0(sm->xxkey, sm->xxkey_len, ssid, ssid_len, mdid,
+ r0kh, r0kh_len, sm->addr,
+ pmk_r0, pmk_r0_name,
+ wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) < 0)
+ return -1;
+ wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", pmk_r0, pmk_r0_len);
+ wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name", pmk_r0_name, WPA_PMK_NAME_LEN);
+ if (!psk_local || !wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt))
+ wpa_ft_store_pmk_r0(sm->wpa_auth, sm->addr, pmk_r0, pmk_r0_len,
+ pmk_r0_name,
+ sm->pairwise, &vlan, expires_in,
+ session_timeout, identity, identity_len,
+ radius_cui, radius_cui_len);
+
+ if (wpa_derive_pmk_r1(pmk_r0, pmk_r0_len, pmk_r0_name, r1kh, sm->addr,
+ pmk_r1, sm->pmk_r1_name) < 0)
+ return -1;
+ wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", pmk_r1, pmk_r1_len);
wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", sm->pmk_r1_name,
WPA_PMK_NAME_LEN);
- wpa_ft_store_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1, sm->pmk_r1_name,
- sm->pairwise);
-
- return wpa_pmk_r1_to_ptk(pmk_r1, sm->SNonce, sm->ANonce, sm->addr,
- sm->wpa_auth->addr, sm->pmk_r1_name,
+ if (!psk_local || !wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt))
+ wpa_ft_store_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1, pmk_r1_len,
+ sm->pmk_r1_name, sm->pairwise, &vlan,
+ expires_in, session_timeout, identity,
+ identity_len, radius_cui, radius_cui_len);
+
+ return wpa_pmk_r1_to_ptk(pmk_r1, pmk_r1_len, sm->SNonce, sm->ANonce,
+ sm->addr, sm->wpa_auth->addr, sm->pmk_r1_name,
ptk, ptk_name, sm->wpa_key_mgmt, sm->pairwise);
}
@@ -406,9 +2149,9 @@ int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk,
static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth,
const u8 *addr, int idx, u8 *seq)
{
- if (wpa_auth->cb.get_seqnum == NULL)
+ if (wpa_auth->cb->get_seqnum == NULL)
return -1;
- return wpa_auth->cb.get_seqnum(wpa_auth->cb.ctx, addr, idx, seq);
+ return wpa_auth->cb->get_seqnum(wpa_auth->cb_ctx, addr, idx, seq);
}
@@ -420,6 +2163,16 @@ static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len)
const u8 *key;
size_t key_len;
u8 keybuf[32];
+ const u8 *kek;
+ size_t kek_len;
+
+ if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
+ kek = sm->PTK.kek2;
+ kek_len = sm->PTK.kek2_len;
+ } else {
+ kek = sm->PTK.kek;
+ kek_len = sm->PTK.kek_len;
+ }
key_len = gsm->GTK_len;
if (key_len > sizeof(keybuf))
@@ -458,8 +2211,10 @@ static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len)
WPA_PUT_LE16(&subelem[2], gsm->GN & 0x03);
subelem[4] = gsm->GTK_len;
wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, subelem + 5);
- if (aes_wrap(sm->PTK.kek, sm->PTK.kek_len, key_len / 8, key,
- subelem + 13)) {
+ if (aes_wrap(kek, kek_len, key_len / 8, key, subelem + 13)) {
+ wpa_printf(MSG_DEBUG,
+ "FT: GTK subelem encryption failed: kek_len=%d",
+ (int) kek_len);
os_free(subelem);
return NULL;
}
@@ -475,10 +2230,23 @@ static u8 * wpa_ft_igtk_subelem(struct wpa_state_machine *sm, size_t *len)
u8 *subelem, *pos;
struct wpa_group *gsm = sm->group;
size_t subelem_len;
+ const u8 *kek;
+ size_t kek_len;
+ size_t igtk_len;
+
+ if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
+ kek = sm->PTK.kek2;
+ kek_len = sm->PTK.kek2_len;
+ } else {
+ kek = sm->PTK.kek;
+ kek_len = sm->PTK.kek_len;
+ }
+
+ igtk_len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
/* Sub-elem ID[1] | Length[1] | KeyID[2] | IPN[6] | Key Length[1] |
* Key[16+8] */
- subelem_len = 1 + 1 + 2 + 6 + 1 + WPA_IGTK_LEN + 8;
+ subelem_len = 1 + 1 + 2 + 6 + 1 + igtk_len + 8;
subelem = os_zalloc(subelem_len);
if (subelem == NULL)
return NULL;
@@ -490,9 +2258,12 @@ static u8 * wpa_ft_igtk_subelem(struct wpa_state_machine *sm, size_t *len)
pos += 2;
wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos);
pos += 6;
- *pos++ = WPA_IGTK_LEN;
- if (aes_wrap(sm->PTK.kek, sm->PTK.kek_len, WPA_IGTK_LEN / 8,
+ *pos++ = igtk_len;
+ if (aes_wrap(kek, kek_len, igtk_len / 8,
gsm->IGTK[gsm->GN_igtk - 4], pos)) {
+ wpa_printf(MSG_DEBUG,
+ "FT: IGTK subelem encryption failed: kek_len=%d",
+ (int) kek_len);
os_free(subelem);
return NULL;
}
@@ -639,17 +2410,21 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
const u8 *req_ies, size_t req_ies_len)
{
u8 *end, *mdie, *ftie, *rsnie = NULL, *r0kh_id, *subelem = NULL;
+ u8 *fte_mic, *elem_count;
size_t mdie_len, ftie_len, rsnie_len = 0, r0kh_id_len, subelem_len = 0;
int res;
struct wpa_auth_config *conf;
- struct rsn_ftie *_ftie;
struct wpa_ft_ies parse;
u8 *ric_start;
u8 *anonce, *snonce;
+ const u8 *kck;
+ size_t kck_len;
+ int use_sha384;
if (sm == NULL)
return pos;
+ use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
conf = &sm->wpa_auth->conf;
if (!wpa_key_mgmt_ft(sm->wpa_key_mgmt))
@@ -657,14 +2432,28 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
end = pos + max_len;
- if (auth_alg == WLAN_AUTH_FT) {
+ if (auth_alg == WLAN_AUTH_FT ||
+ ((auth_alg == WLAN_AUTH_FILS_SK ||
+ auth_alg == WLAN_AUTH_FILS_SK_PFS ||
+ auth_alg == WLAN_AUTH_FILS_PK) &&
+ (sm->wpa_key_mgmt & (WPA_KEY_MGMT_FT_FILS_SHA256 |
+ WPA_KEY_MGMT_FT_FILS_SHA384)))) {
+ if (!sm->pmk_r1_name_valid) {
+ wpa_printf(MSG_ERROR,
+ "FT: PMKR1Name is not valid for Assoc Resp RSNE");
+ return NULL;
+ }
+ wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name for Assoc Resp RSNE",
+ sm->pmk_r1_name, WPA_PMK_NAME_LEN);
/*
* RSN (only present if this is a Reassociation Response and
- * part of a fast BSS transition)
+ * part of a fast BSS transition; or if this is a
+ * (Re)Association Response frame during an FT initial mobility
+ * domain association using FILS)
*/
res = wpa_write_rsn_ie(conf, pos, end - pos, sm->pmk_r1_name);
if (res < 0)
- return pos;
+ return NULL;
rsnie = pos;
rsnie_len = res;
pos += res;
@@ -673,7 +2462,7 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
/* Mobility Domain Information */
res = wpa_write_mdie(conf, pos, end - pos);
if (res < 0)
- return pos;
+ return NULL;
mdie = pos;
mdie_len = res;
pos += res;
@@ -681,6 +2470,11 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
/* Fast BSS Transition Information */
if (auth_alg == WLAN_AUTH_FT) {
subelem = wpa_ft_gtk_subelem(sm, &subelem_len);
+ if (!subelem) {
+ wpa_printf(MSG_DEBUG,
+ "FT: Failed to add GTK subelement");
+ return NULL;
+ }
r0kh_id = sm->r0kh_id;
r0kh_id_len = sm->r0kh_id_len;
anonce = sm->ANonce;
@@ -692,14 +2486,16 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
u8 *nbuf;
igtk = wpa_ft_igtk_subelem(sm, &igtk_len);
if (igtk == NULL) {
+ wpa_printf(MSG_DEBUG,
+ "FT: Failed to add IGTK subelement");
os_free(subelem);
- return pos;
+ return NULL;
}
nbuf = os_realloc(subelem, subelem_len + igtk_len);
if (nbuf == NULL) {
os_free(subelem);
os_free(igtk);
- return pos;
+ return NULL;
}
subelem = nbuf;
os_memcpy(subelem + subelem_len, igtk, igtk_len);
@@ -707,50 +2503,101 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
os_free(igtk);
}
#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_OCV
+ if (wpa_auth_uses_ocv(sm)) {
+ struct wpa_channel_info ci;
+ u8 *nbuf, *ocipos;
+
+ if (wpa_channel_info(sm->wpa_auth, &ci) != 0) {
+ wpa_printf(MSG_WARNING,
+ "Failed to get channel info for OCI element");
+ os_free(subelem);
+ return NULL;
+ }
+
+ subelem_len += 2 + OCV_OCI_LEN;
+ nbuf = os_realloc(subelem, subelem_len);
+ if (!nbuf) {
+ os_free(subelem);
+ return NULL;
+ }
+ subelem = nbuf;
+
+ ocipos = subelem + subelem_len - 2 - OCV_OCI_LEN;
+ *ocipos++ = FTIE_SUBELEM_OCI;
+ *ocipos++ = OCV_OCI_LEN;
+ if (ocv_insert_oci(&ci, &ocipos) < 0) {
+ os_free(subelem);
+ return NULL;
+ }
+ }
+#endif /* CONFIG_OCV */
} else {
r0kh_id = conf->r0_key_holder;
r0kh_id_len = conf->r0_key_holder_len;
anonce = NULL;
snonce = NULL;
}
- res = wpa_write_ftie(conf, r0kh_id, r0kh_id_len, anonce, snonce, pos,
- end - pos, subelem, subelem_len);
+ res = wpa_write_ftie(conf, use_sha384, r0kh_id, r0kh_id_len,
+ anonce, snonce, pos, end - pos,
+ subelem, subelem_len);
os_free(subelem);
if (res < 0)
- return pos;
+ return NULL;
ftie = pos;
ftie_len = res;
pos += res;
- _ftie = (struct rsn_ftie *) (ftie + 2);
+ if (use_sha384) {
+ struct rsn_ftie_sha384 *_ftie =
+ (struct rsn_ftie_sha384 *) (ftie + 2);
+
+ fte_mic = _ftie->mic;
+ elem_count = &_ftie->mic_control[1];
+ } else {
+ struct rsn_ftie *_ftie = (struct rsn_ftie *) (ftie + 2);
+
+ fte_mic = _ftie->mic;
+ elem_count = &_ftie->mic_control[1];
+ }
if (auth_alg == WLAN_AUTH_FT)
- _ftie->mic_control[1] = 3; /* Information element count */
+ *elem_count = 3; /* Information element count */
ric_start = pos;
- if (wpa_ft_parse_ies(req_ies, req_ies_len, &parse) == 0 && parse.ric) {
+ if (wpa_ft_parse_ies(req_ies, req_ies_len, &parse, use_sha384) == 0
+ && parse.ric) {
pos = wpa_ft_process_ric(sm, pos, end, parse.ric,
parse.ric_len);
if (auth_alg == WLAN_AUTH_FT)
- _ftie->mic_control[1] +=
+ *elem_count +=
ieee802_11_ie_count(ric_start,
pos - ric_start);
}
if (ric_start == pos)
ric_start = NULL;
+ if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
+ kck = sm->PTK.kck2;
+ kck_len = sm->PTK.kck2_len;
+ } else {
+ kck = sm->PTK.kck;
+ kck_len = sm->PTK.kck_len;
+ }
if (auth_alg == WLAN_AUTH_FT &&
- wpa_ft_mic(sm->PTK.kck, sm->PTK.kck_len, sm->addr,
- sm->wpa_auth->addr, 6,
+ wpa_ft_mic(kck, kck_len, sm->addr, sm->wpa_auth->addr, 6,
mdie, mdie_len, ftie, ftie_len,
rsnie, rsnie_len,
ric_start, ric_start ? pos - ric_start : 0,
- _ftie->mic) < 0)
+ fte_mic) < 0) {
wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC");
+ return NULL;
+ }
os_free(sm->assoc_resp_ftie);
sm->assoc_resp_ftie = os_malloc(ftie_len);
- if (sm->assoc_resp_ftie)
- os_memcpy(sm->assoc_resp_ftie, ftie, ftie_len);
+ if (!sm->assoc_resp_ftie)
+ return NULL;
+ os_memcpy(sm->assoc_resp_ftie, ftie, ftie_len);
return pos;
}
@@ -761,10 +2608,10 @@ static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth,
enum wpa_alg alg, const u8 *addr, int idx,
u8 *key, size_t key_len)
{
- if (wpa_auth->cb.set_key == NULL)
+ if (wpa_auth->cb->set_key == NULL)
return -1;
- return wpa_auth->cb.set_key(wpa_auth->cb.ctx, vlan_id, alg, addr, idx,
- key, key_len);
+ return wpa_auth->cb->set_key(wpa_auth->cb_ctx, vlan_id, alg, addr, idx,
+ key, key_len);
}
@@ -806,20 +2653,221 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm)
}
+/* Derive PMK-R1 from PSK, check all available PSK */
+static int wpa_ft_psk_pmk_r1(struct wpa_state_machine *sm,
+ const u8 *req_pmk_r1_name,
+ u8 *out_pmk_r1, int *out_pairwise,
+ struct vlan_description *out_vlan,
+ const u8 **out_identity, size_t *out_identity_len,
+ const u8 **out_radius_cui,
+ size_t *out_radius_cui_len,
+ int *out_session_timeout)
+{
+ const u8 *pmk = NULL;
+ u8 pmk_r0[PMK_LEN], pmk_r0_name[WPA_PMK_NAME_LEN];
+ u8 pmk_r1[PMK_LEN], pmk_r1_name[WPA_PMK_NAME_LEN];
+ struct wpa_authenticator *wpa_auth = sm->wpa_auth;
+ const u8 *mdid = wpa_auth->conf.mobility_domain;
+ const u8 *r0kh = sm->r0kh_id;
+ size_t r0kh_len = sm->r0kh_id_len;
+ const u8 *r1kh = wpa_auth->conf.r1_key_holder;
+ const u8 *ssid = wpa_auth->conf.ssid;
+ size_t ssid_len = wpa_auth->conf.ssid_len;
+ int pairwise;
+
+ pairwise = sm->pairwise;
+
+ for (;;) {
+ pmk = wpa_ft_get_psk(wpa_auth, sm->addr, sm->p2p_dev_addr,
+ pmk);
+ if (pmk == NULL)
+ break;
+
+ if (wpa_derive_pmk_r0(pmk, PMK_LEN, ssid, ssid_len, mdid, r0kh,
+ r0kh_len, sm->addr,
+ pmk_r0, pmk_r0_name, 0) < 0 ||
+ wpa_derive_pmk_r1(pmk_r0, PMK_LEN, pmk_r0_name, r1kh,
+ sm->addr, pmk_r1, pmk_r1_name) < 0 ||
+ os_memcmp_const(pmk_r1_name, req_pmk_r1_name,
+ WPA_PMK_NAME_LEN) != 0)
+ continue;
+
+ /* We found a PSK that matches the requested pmk_r1_name */
+ wpa_printf(MSG_DEBUG,
+ "FT: Found PSK to generate PMK-R1 locally");
+ os_memcpy(out_pmk_r1, pmk_r1, PMK_LEN);
+ if (out_pairwise)
+ *out_pairwise = pairwise;
+ os_memcpy(sm->PMK, pmk, PMK_LEN);
+ sm->pmk_len = PMK_LEN;
+ if (out_vlan &&
+ wpa_ft_get_vlan(sm->wpa_auth, sm->addr, out_vlan) < 0) {
+ wpa_printf(MSG_DEBUG, "FT: vlan not available for STA "
+ MACSTR, MAC2STR(sm->addr));
+ return -1;
+ }
+
+ if (out_identity && out_identity_len) {
+ *out_identity_len = wpa_ft_get_identity(
+ sm->wpa_auth, sm->addr, out_identity);
+ }
+
+ if (out_radius_cui && out_radius_cui_len) {
+ *out_radius_cui_len = wpa_ft_get_radius_cui(
+ sm->wpa_auth, sm->addr, out_radius_cui);
+ }
+
+ if (out_session_timeout) {
+ *out_session_timeout = wpa_ft_get_session_timeout(
+ sm->wpa_auth, sm->addr);
+ }
+
+ return 0;
+ }
+
+ wpa_printf(MSG_DEBUG,
+ "FT: Did not find PSK to generate PMK-R1 locally");
+ return -1;
+}
+
+
+/* Detect the configuration the station asked for.
+ * Required to detect FT-PSK and pairwise cipher.
+ */
+static int wpa_ft_set_key_mgmt(struct wpa_state_machine *sm,
+ struct wpa_ft_ies *parse)
+{
+ int key_mgmt, ciphers;
+
+ if (sm->wpa_key_mgmt)
+ return 0;
+
+ key_mgmt = parse->key_mgmt & sm->wpa_auth->conf.wpa_key_mgmt;
+ if (!key_mgmt) {
+ wpa_printf(MSG_DEBUG, "FT: Invalid key mgmt (0x%x) from "
+ MACSTR, parse->key_mgmt, MAC2STR(sm->addr));
+ return -1;
+ }
+ if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
+ sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
+#ifdef CONFIG_SHA384
+ else if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X_SHA384)
+ sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
+#endif /* CONFIG_SHA384 */
+ else if (key_mgmt & WPA_KEY_MGMT_FT_PSK)
+ sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_PSK;
+#ifdef CONFIG_FILS
+ else if (key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256)
+ sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
+ else if (key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384)
+ sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
+#endif /* CONFIG_FILS */
+ ciphers = parse->pairwise_cipher & sm->wpa_auth->conf.rsn_pairwise;
+ if (!ciphers) {
+ wpa_printf(MSG_DEBUG, "FT: Invalid pairwise cipher (0x%x) from "
+ MACSTR,
+ parse->pairwise_cipher, MAC2STR(sm->addr));
+ return -1;
+ }
+ sm->pairwise = wpa_pick_pairwise_cipher(ciphers, 0);
+
+ return 0;
+}
+
+
+static int wpa_ft_local_derive_pmk_r1(struct wpa_authenticator *wpa_auth,
+ struct wpa_state_machine *sm,
+ const u8 *r0kh_id, size_t r0kh_id_len,
+ const u8 *req_pmk_r0_name,
+ const u8 *req_pmk_r1_name,
+ u8 *out_pmk_r1, int *out_pairwise,
+ struct vlan_description *vlan,
+ const u8 **identity, size_t *identity_len,
+ const u8 **radius_cui,
+ size_t *radius_cui_len,
+ int *out_session_timeout)
+{
+ struct wpa_auth_config *conf = &wpa_auth->conf;
+ const struct wpa_ft_pmk_r0_sa *r0;
+ u8 pmk_r1_name[WPA_PMK_NAME_LEN];
+ int expires_in = 0;
+ int session_timeout = 0;
+ struct os_reltime now;
+
+ if (conf->r0_key_holder_len != r0kh_id_len ||
+ os_memcmp(conf->r0_key_holder, r0kh_id, conf->r0_key_holder_len) !=
+ 0)
+ return -1; /* not our R0KH-ID */
+
+ wpa_printf(MSG_DEBUG, "FT: STA R0KH-ID matching local configuration");
+ if (wpa_ft_fetch_pmk_r0(sm->wpa_auth, sm->addr, req_pmk_r0_name, &r0) <
+ 0)
+ return -1; /* no matching PMKR0Name in local cache */
+
+ wpa_printf(MSG_DEBUG, "FT: Requested PMKR0Name found in local cache");
+
+ if (wpa_derive_pmk_r1(r0->pmk_r0, r0->pmk_r0_len, r0->pmk_r0_name,
+ conf->r1_key_holder,
+ sm->addr, out_pmk_r1, pmk_r1_name) < 0)
+ return -1;
+ wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", out_pmk_r1, r0->pmk_r0_len);
+ wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", pmk_r1_name, WPA_PMK_NAME_LEN);
+
+ os_get_reltime(&now);
+ if (r0->expiration)
+ expires_in = r0->expiration - now.sec;
+
+ if (r0->session_timeout)
+ session_timeout = r0->session_timeout - now.sec;
+
+ wpa_ft_store_pmk_r1(wpa_auth, sm->addr, out_pmk_r1, r0->pmk_r0_len,
+ pmk_r1_name,
+ sm->pairwise, r0->vlan, expires_in, session_timeout,
+ r0->identity, r0->identity_len,
+ r0->radius_cui, r0->radius_cui_len);
+
+ *out_pairwise = sm->pairwise;
+ if (vlan) {
+ if (r0->vlan)
+ *vlan = *r0->vlan;
+ else
+ os_memset(vlan, 0, sizeof(*vlan));
+ }
+
+ if (identity && identity_len) {
+ *identity = r0->identity;
+ *identity_len = r0->identity_len;
+ }
+
+ if (radius_cui && radius_cui_len) {
+ *radius_cui = r0->radius_cui;
+ *radius_cui_len = r0->radius_cui_len;
+ }
+
+ *out_session_timeout = session_timeout;
+
+ return 0;
+}
+
+
static int wpa_ft_process_auth_req(struct wpa_state_machine *sm,
const u8 *ies, size_t ies_len,
u8 **resp_ies, size_t *resp_ies_len)
{
struct rsn_mdie *mdie;
- struct rsn_ftie *ftie;
- u8 pmk_r1[PMK_LEN], pmk_r1_name[WPA_PMK_NAME_LEN];
+ u8 pmk_r1[PMK_LEN_MAX], pmk_r1_name[WPA_PMK_NAME_LEN];
u8 ptk_name[WPA_PMK_NAME_LEN];
struct wpa_auth_config *conf;
struct wpa_ft_ies parse;
size_t buflen;
int ret;
u8 *pos, *end;
- int pairwise;
+ int pairwise, session_timeout = 0;
+ struct vlan_description vlan;
+ const u8 *identity, *radius_cui;
+ size_t identity_len = 0, radius_cui_len = 0;
+ int use_sha384;
+ size_t pmk_r1_len;
*resp_ies = NULL;
*resp_ies_len = 0;
@@ -830,10 +2878,12 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm,
wpa_hexdump(MSG_DEBUG, "FT: Received authentication frame IEs",
ies, ies_len);
- if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) {
+ if (wpa_ft_parse_ies(ies, ies_len, &parse, -1)) {
wpa_printf(MSG_DEBUG, "FT: Failed to parse FT IEs");
return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
+ use_sha384 = wpa_key_mgmt_sha384(parse.key_mgmt);
+ pmk_r1_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN;
mdie = (struct rsn_mdie *) parse.mdie;
if (mdie == NULL || parse.mdie_len < sizeof(*mdie) ||
@@ -844,13 +2894,27 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm,
return WLAN_STATUS_INVALID_MDIE;
}
- ftie = (struct rsn_ftie *) parse.ftie;
- if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) {
- wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
- return WLAN_STATUS_INVALID_FTIE;
- }
+ if (use_sha384) {
+ struct rsn_ftie_sha384 *ftie;
+
+ ftie = (struct rsn_ftie_sha384 *) parse.ftie;
+ if (!ftie || parse.ftie_len < sizeof(*ftie)) {
+ wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
+ return WLAN_STATUS_INVALID_FTIE;
+ }
+
+ os_memcpy(sm->SNonce, ftie->snonce, WPA_NONCE_LEN);
+ } else {
+ struct rsn_ftie *ftie;
+
+ ftie = (struct rsn_ftie *) parse.ftie;
+ if (!ftie || parse.ftie_len < sizeof(*ftie)) {
+ wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
+ return WLAN_STATUS_INVALID_FTIE;
+ }
- os_memcpy(sm->SNonce, ftie->snonce, WPA_NONCE_LEN);
+ os_memcpy(sm->SNonce, ftie->snonce, WPA_NONCE_LEN);
+ }
if (parse.r0kh_id == NULL) {
wpa_printf(MSG_DEBUG, "FT: Invalid FTIE - no R0KH-ID");
@@ -867,28 +2931,62 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm,
return WLAN_STATUS_INVALID_PMKID;
}
+ if (wpa_ft_set_key_mgmt(sm, &parse) < 0)
+ return WLAN_STATUS_UNSPECIFIED_FAILURE;
+
wpa_hexdump(MSG_DEBUG, "FT: Requested PMKR0Name",
parse.rsn_pmkid, WPA_PMK_NAME_LEN);
- wpa_derive_pmk_r1_name(parse.rsn_pmkid,
- sm->wpa_auth->conf.r1_key_holder, sm->addr,
- pmk_r1_name);
+ if (wpa_derive_pmk_r1_name(parse.rsn_pmkid,
+ sm->wpa_auth->conf.r1_key_holder, sm->addr,
+ pmk_r1_name, use_sha384) < 0)
+ return WLAN_STATUS_UNSPECIFIED_FAILURE;
wpa_hexdump(MSG_DEBUG, "FT: Derived requested PMKR1Name",
pmk_r1_name, WPA_PMK_NAME_LEN);
- if (wpa_ft_fetch_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1_name, pmk_r1,
- &pairwise) < 0) {
+ if (conf->ft_psk_generate_local &&
+ wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) {
+ if (wpa_ft_psk_pmk_r1(sm, pmk_r1_name, pmk_r1, &pairwise,
+ &vlan, &identity, &identity_len,
+ &radius_cui, &radius_cui_len,
+ &session_timeout) < 0)
+ return WLAN_STATUS_INVALID_PMKID;
+ wpa_printf(MSG_DEBUG,
+ "FT: Generated PMK-R1 for FT-PSK locally");
+ } else if (wpa_ft_fetch_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1_name,
+ pmk_r1, &pmk_r1_len, &pairwise, &vlan,
+ &identity, &identity_len, &radius_cui,
+ &radius_cui_len, &session_timeout) < 0) {
+ wpa_printf(MSG_DEBUG,
+ "FT: No PMK-R1 available in local cache for the requested PMKR1Name");
+ if (wpa_ft_local_derive_pmk_r1(sm->wpa_auth, sm,
+ parse.r0kh_id, parse.r0kh_id_len,
+ parse.rsn_pmkid,
+ pmk_r1_name, pmk_r1, &pairwise,
+ &vlan, &identity, &identity_len,
+ &radius_cui, &radius_cui_len,
+ &session_timeout) == 0) {
+ wpa_printf(MSG_DEBUG,
+ "FT: Generated PMK-R1 based on local PMK-R0");
+ goto pmk_r1_derived;
+ }
+
if (wpa_ft_pull_pmk_r1(sm, ies, ies_len, parse.rsn_pmkid) < 0) {
- wpa_printf(MSG_DEBUG, "FT: Did not have matching "
- "PMK-R1 and unknown R0KH-ID");
+ wpa_printf(MSG_DEBUG,
+ "FT: Did not have matching PMK-R1 and either unknown or blocked R0KH-ID or NAK from R0KH");
return WLAN_STATUS_INVALID_PMKID;
}
return -1; /* Status pending */
+ } else {
+ wpa_printf(MSG_DEBUG, "FT: Found PMKR1Name from local cache");
}
- wpa_hexdump_key(MSG_DEBUG, "FT: Selected PMK-R1", pmk_r1, PMK_LEN);
+pmk_r1_derived:
+ wpa_hexdump_key(MSG_DEBUG, "FT: Selected PMK-R1", pmk_r1, pmk_r1_len);
sm->pmk_r1_name_valid = 1;
os_memcpy(sm->pmk_r1_name, pmk_r1_name, WPA_PMK_NAME_LEN);
+ os_memcpy(sm->pmk_r1, pmk_r1, pmk_r1_len);
+ sm->pmk_r1_len = pmk_r1_len;
if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
wpa_printf(MSG_DEBUG, "FT: Failed to get random data for "
@@ -901,8 +2999,8 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm,
wpa_hexdump(MSG_DEBUG, "FT: Generated ANonce",
sm->ANonce, WPA_NONCE_LEN);
- if (wpa_pmk_r1_to_ptk(pmk_r1, sm->SNonce, sm->ANonce, sm->addr,
- sm->wpa_auth->addr, pmk_r1_name,
+ if (wpa_pmk_r1_to_ptk(pmk_r1, pmk_r1_len, sm->SNonce, sm->ANonce,
+ sm->addr, sm->wpa_auth->addr, pmk_r1_name,
&sm->PTK, ptk_name, sm->wpa_key_mgmt,
pairwise) < 0)
return WLAN_STATUS_UNSPECIFIED_FAILURE;
@@ -912,44 +3010,51 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm,
sm->tk_already_set = FALSE;
wpa_ft_install_ptk(sm);
+ if (wpa_ft_set_vlan(sm->wpa_auth, sm->addr, &vlan) < 0) {
+ wpa_printf(MSG_DEBUG, "FT: Failed to configure VLAN");
+ return WLAN_STATUS_UNSPECIFIED_FAILURE;
+ }
+ if (wpa_ft_set_identity(sm->wpa_auth, sm->addr,
+ identity, identity_len) < 0 ||
+ wpa_ft_set_radius_cui(sm->wpa_auth, sm->addr,
+ radius_cui, radius_cui_len) < 0) {
+ wpa_printf(MSG_DEBUG, "FT: Failed to configure identity/CUI");
+ return WLAN_STATUS_UNSPECIFIED_FAILURE;
+ }
+ wpa_ft_set_session_timeout(sm->wpa_auth, sm->addr, session_timeout);
+
buflen = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) +
2 + FT_R1KH_ID_LEN + 200;
*resp_ies = os_zalloc(buflen);
- if (*resp_ies == NULL) {
- return WLAN_STATUS_UNSPECIFIED_FAILURE;
- }
+ if (*resp_ies == NULL)
+ goto fail;
pos = *resp_ies;
end = *resp_ies + buflen;
ret = wpa_write_rsn_ie(conf, pos, end - pos, parse.rsn_pmkid);
- if (ret < 0) {
- os_free(*resp_ies);
- *resp_ies = NULL;
- return WLAN_STATUS_UNSPECIFIED_FAILURE;
- }
+ if (ret < 0)
+ goto fail;
pos += ret;
ret = wpa_write_mdie(conf, pos, end - pos);
- if (ret < 0) {
- os_free(*resp_ies);
- *resp_ies = NULL;
- return WLAN_STATUS_UNSPECIFIED_FAILURE;
- }
+ if (ret < 0)
+ goto fail;
pos += ret;
- ret = wpa_write_ftie(conf, parse.r0kh_id, parse.r0kh_id_len,
+ ret = wpa_write_ftie(conf, use_sha384, parse.r0kh_id, parse.r0kh_id_len,
sm->ANonce, sm->SNonce, pos, end - pos, NULL, 0);
- if (ret < 0) {
- os_free(*resp_ies);
- *resp_ies = NULL;
- return WLAN_STATUS_UNSPECIFIED_FAILURE;
- }
+ if (ret < 0)
+ goto fail;
pos += ret;
*resp_ies_len = pos - *resp_ies;
return WLAN_STATUS_SUCCESS;
+fail:
+ os_free(*resp_ies);
+ *resp_ies = NULL;
+ return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
@@ -977,6 +3082,7 @@ void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid,
sm->ft_pending_cb = cb;
sm->ft_pending_cb_ctx = ctx;
sm->ft_pending_auth_transaction = auth_transaction;
+ sm->ft_pending_pull_left_retries = sm->wpa_auth->conf.rkh_pull_retries;
res = wpa_ft_process_auth_req(sm, ies, ies_len, &resp_ies,
&resp_ies_len);
if (res < 0) {
@@ -1000,17 +3106,23 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
{
struct wpa_ft_ies parse;
struct rsn_mdie *mdie;
- struct rsn_ftie *ftie;
u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN];
size_t mic_len = 16;
unsigned int count;
+ const u8 *kck;
+ size_t kck_len;
+ int use_sha384;
+ const u8 *anonce, *snonce, *fte_mic;
+ u8 fte_elem_count;
if (sm == NULL)
return WLAN_STATUS_UNSPECIFIED_FAILURE;
+ use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
+
wpa_hexdump(MSG_DEBUG, "FT: Reassoc Req IEs", ies, ies_len);
- if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) {
+ if (wpa_ft_parse_ies(ies, ies_len, &parse, use_sha384) < 0) {
wpa_printf(MSG_DEBUG, "FT: Failed to parse FT IEs");
return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
@@ -1041,34 +3153,56 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
return WLAN_STATUS_INVALID_MDIE;
}
- ftie = (struct rsn_ftie *) parse.ftie;
- if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) {
- wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
- return WLAN_STATUS_INVALID_FTIE;
+ if (use_sha384) {
+ struct rsn_ftie_sha384 *ftie;
+
+ ftie = (struct rsn_ftie_sha384 *) parse.ftie;
+ if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) {
+ wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
+ return WLAN_STATUS_INVALID_FTIE;
+ }
+
+ anonce = ftie->anonce;
+ snonce = ftie->snonce;
+ fte_elem_count = ftie->mic_control[1];
+ fte_mic = ftie->mic;
+ } else {
+ struct rsn_ftie *ftie;
+
+ ftie = (struct rsn_ftie *) parse.ftie;
+ if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) {
+ wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
+ return WLAN_STATUS_INVALID_FTIE;
+ }
+
+ anonce = ftie->anonce;
+ snonce = ftie->snonce;
+ fte_elem_count = ftie->mic_control[1];
+ fte_mic = ftie->mic;
}
- if (os_memcmp(ftie->snonce, sm->SNonce, WPA_NONCE_LEN) != 0) {
+ if (os_memcmp(snonce, sm->SNonce, WPA_NONCE_LEN) != 0) {
wpa_printf(MSG_DEBUG, "FT: SNonce mismatch in FTIE");
wpa_hexdump(MSG_DEBUG, "FT: Received SNonce",
- ftie->snonce, WPA_NONCE_LEN);
+ snonce, WPA_NONCE_LEN);
wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce",
sm->SNonce, WPA_NONCE_LEN);
- return -1;
+ return WLAN_STATUS_INVALID_FTIE;
}
- if (os_memcmp(ftie->anonce, sm->ANonce, WPA_NONCE_LEN) != 0) {
+ if (os_memcmp(anonce, sm->ANonce, WPA_NONCE_LEN) != 0) {
wpa_printf(MSG_DEBUG, "FT: ANonce mismatch in FTIE");
wpa_hexdump(MSG_DEBUG, "FT: Received ANonce",
- ftie->anonce, WPA_NONCE_LEN);
+ anonce, WPA_NONCE_LEN);
wpa_hexdump(MSG_DEBUG, "FT: Expected ANonce",
sm->ANonce, WPA_NONCE_LEN);
- return -1;
+ return WLAN_STATUS_INVALID_FTIE;
}
if (parse.r0kh_id == NULL) {
wpa_printf(MSG_DEBUG, "FT: No R0KH-ID subelem in FTIE");
- return -1;
+ return WLAN_STATUS_INVALID_FTIE;
}
if (parse.r0kh_id_len != sm->r0kh_id_len ||
@@ -1080,12 +3214,12 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
parse.r0kh_id, parse.r0kh_id_len);
wpa_hexdump(MSG_DEBUG, "FT: The current R0KH-ID",
sm->r0kh_id, sm->r0kh_id_len);
- return -1;
+ return WLAN_STATUS_INVALID_FTIE;
}
if (parse.r1kh_id == NULL) {
wpa_printf(MSG_DEBUG, "FT: No R1KH-ID subelem in FTIE");
- return -1;
+ return WLAN_STATUS_INVALID_FTIE;
}
if (os_memcmp_const(parse.r1kh_id, sm->wpa_auth->conf.r1_key_holder,
@@ -1096,7 +3230,7 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
parse.r1kh_id, FT_R1KH_ID_LEN);
wpa_hexdump(MSG_DEBUG, "FT: Expected R1KH-ID",
sm->wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN);
- return -1;
+ return WLAN_STATUS_INVALID_FTIE;
}
if (parse.rsn_pmkid == NULL ||
@@ -1104,21 +3238,27 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
{
wpa_printf(MSG_DEBUG, "FT: No matching PMKR1Name (PMKID) in "
"RSNIE (pmkid=%d)", !!parse.rsn_pmkid);
- return -1;
+ return WLAN_STATUS_INVALID_PMKID;
}
count = 3;
if (parse.ric)
count += ieee802_11_ie_count(parse.ric, parse.ric_len);
- if (ftie->mic_control[1] != count) {
+ if (fte_elem_count != count) {
wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in MIC "
"Control: received %u expected %u",
- ftie->mic_control[1], count);
- return -1;
+ fte_elem_count, count);
+ return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
- if (wpa_ft_mic(sm->PTK.kck, sm->PTK.kck_len, sm->addr,
- sm->wpa_auth->addr, 5,
+ if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
+ kck = sm->PTK.kck2;
+ kck_len = sm->PTK.kck2_len;
+ } else {
+ kck = sm->PTK.kck;
+ kck_len = sm->PTK.kck_len;
+ }
+ if (wpa_ft_mic(kck, kck_len, sm->addr, sm->wpa_auth->addr, 5,
parse.mdie - 2, parse.mdie_len + 2,
parse.ftie - 2, parse.ftie_len + 2,
parse.rsn - 2, parse.rsn_len + 2,
@@ -1128,12 +3268,12 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
- if (os_memcmp_const(mic, ftie->mic, mic_len) != 0) {
+ if (os_memcmp_const(mic, fte_mic, mic_len) != 0) {
wpa_printf(MSG_DEBUG, "FT: Invalid MIC in FTIE");
wpa_printf(MSG_DEBUG, "FT: addr=" MACSTR " auth_addr=" MACSTR,
MAC2STR(sm->addr), MAC2STR(sm->wpa_auth->addr));
wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC",
- ftie->mic, mic_len);
+ fte_mic, mic_len);
wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", mic, mic_len);
wpa_hexdump(MSG_MSGDUMP, "FT: MDIE",
parse.mdie - 2, parse.mdie_len + 2);
@@ -1144,6 +3284,32 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
return WLAN_STATUS_INVALID_FTIE;
}
+#ifdef CONFIG_OCV
+ if (wpa_auth_uses_ocv(sm)) {
+ struct wpa_channel_info ci;
+ int tx_chanwidth;
+ int tx_seg1_idx;
+
+ if (wpa_channel_info(sm->wpa_auth, &ci) != 0) {
+ wpa_printf(MSG_WARNING,
+ "Failed to get channel info to validate received OCI in (Re)Assoc Request");
+ return WLAN_STATUS_UNSPECIFIED_FAILURE;
+ }
+
+ if (get_sta_tx_parameters(sm,
+ channel_width_to_int(ci.chanwidth),
+ ci.seg1_idx, &tx_chanwidth,
+ &tx_seg1_idx) < 0)
+ return WLAN_STATUS_UNSPECIFIED_FAILURE;
+
+ if (ocv_verify_tx_params(parse.oci, parse.oci_len, &ci,
+ tx_chanwidth, tx_seg1_idx) != 0) {
+ wpa_printf(MSG_WARNING, "%s", ocv_errorstr);
+ return WLAN_STATUS_UNSPECIFIED_FAILURE;
+ }
+ }
+#endif /* CONFIG_OCV */
+
return WLAN_STATUS_SUCCESS;
}
@@ -1201,6 +3367,11 @@ int wpa_ft_action_rx(struct wpa_state_machine *sm, const u8 *data, size_t len)
wpa_hexdump(MSG_MSGDUMP, "FT: Action frame body", ies, ies_len);
+ if (!sm->wpa_auth->conf.ft_over_ds) {
+ wpa_printf(MSG_DEBUG, "FT: Over-DS option disabled - reject");
+ return -1;
+ }
+
/* RRB - Forward action frame to the target AP */
frame = os_malloc(sizeof(*frame) + len);
if (frame == NULL)
@@ -1253,6 +3424,7 @@ static int wpa_ft_rrb_rx_request(struct wpa_authenticator *wpa_auth,
sm->ft_pending_cb = wpa_ft_rrb_rx_request_cb;
sm->ft_pending_cb_ctx = sm;
os_memcpy(sm->ft_pending_current_ap, current_ap, ETH_ALEN);
+ sm->ft_pending_pull_left_retries = sm->wpa_auth->conf.rkh_pull_retries;
res = wpa_ft_process_auth_req(sm, body, len, &resp_ies,
&resp_ies_len);
if (res < 0) {
@@ -1318,112 +3490,431 @@ static int wpa_ft_send_rrb_auth_resp(struct wpa_state_machine *sm,
}
+static int wpa_ft_rrb_build_r0(const u8 *key, const size_t key_len,
+ const struct tlv_list *tlvs,
+ const struct wpa_ft_pmk_r0_sa *pmk_r0,
+ const u8 *r1kh_id, const u8 *s1kh_id,
+ const struct tlv_list *tlv_auth,
+ const u8 *src_addr, u8 type,
+ u8 **packet, size_t *packet_len)
+{
+ u8 pmk_r1[PMK_LEN_MAX];
+ size_t pmk_r1_len = pmk_r0->pmk_r0_len;
+ u8 pmk_r1_name[WPA_PMK_NAME_LEN];
+ u8 f_pairwise[sizeof(le16)];
+ u8 f_expires_in[sizeof(le16)];
+ u8 f_session_timeout[sizeof(le32)];
+ int expires_in;
+ int session_timeout;
+ struct os_reltime now;
+ int ret;
+ struct tlv_list sess_tlv[] = {
+ { .type = FT_RRB_PMK_R1, .len = pmk_r1_len,
+ .data = pmk_r1 },
+ { .type = FT_RRB_PMK_R1_NAME, .len = sizeof(pmk_r1_name),
+ .data = pmk_r1_name },
+ { .type = FT_RRB_PAIRWISE, .len = sizeof(f_pairwise),
+ .data = f_pairwise },
+ { .type = FT_RRB_EXPIRES_IN, .len = sizeof(f_expires_in),
+ .data = f_expires_in },
+ { .type = FT_RRB_IDENTITY, .len = pmk_r0->identity_len,
+ .data = pmk_r0->identity },
+ { .type = FT_RRB_RADIUS_CUI, .len = pmk_r0->radius_cui_len,
+ .data = pmk_r0->radius_cui },
+ { .type = FT_RRB_SESSION_TIMEOUT,
+ .len = sizeof(f_session_timeout),
+ .data = f_session_timeout },
+ { .type = FT_RRB_LAST_EMPTY, .len = 0, .data = NULL },
+ };
+
+ if (wpa_derive_pmk_r1(pmk_r0->pmk_r0, pmk_r0->pmk_r0_len,
+ pmk_r0->pmk_r0_name, r1kh_id,
+ s1kh_id, pmk_r1, pmk_r1_name) < 0)
+ return -1;
+ wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1 (for peer AP)",
+ pmk_r1, pmk_r1_len);
+ wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name (for peer AP)",
+ pmk_r1_name, WPA_PMK_NAME_LEN);
+ WPA_PUT_LE16(f_pairwise, pmk_r0->pairwise);
+
+ os_get_reltime(&now);
+ if (pmk_r0->expiration > now.sec)
+ expires_in = pmk_r0->expiration - now.sec;
+ else if (pmk_r0->expiration)
+ expires_in = 1;
+ else
+ expires_in = 0;
+ WPA_PUT_LE16(f_expires_in, expires_in);
+
+ if (pmk_r0->session_timeout > now.sec)
+ session_timeout = pmk_r0->session_timeout - now.sec;
+ else if (pmk_r0->session_timeout)
+ session_timeout = 1;
+ else
+ session_timeout = 0;
+ WPA_PUT_LE32(f_session_timeout, session_timeout);
+
+ ret = wpa_ft_rrb_build(key, key_len, tlvs, sess_tlv, tlv_auth,
+ pmk_r0->vlan, src_addr, type,
+ packet, packet_len);
+
+ os_memset(pmk_r1, 0, sizeof(pmk_r1));
+
+ return ret;
+}
+
+
static int wpa_ft_rrb_rx_pull(struct wpa_authenticator *wpa_auth,
const u8 *src_addr,
- const u8 *data, size_t data_len)
+ const u8 *enc, size_t enc_len,
+ const u8 *auth, size_t auth_len,
+ int no_defer)
{
- struct ft_r0kh_r1kh_pull_frame f;
- const u8 *crypt;
- u8 *plain;
- struct ft_remote_r1kh *r1kh;
- struct ft_r0kh_r1kh_resp_frame resp, r;
- u8 pmk_r0[PMK_LEN];
- int pairwise;
+ const char *msgtype = "pull request";
+ u8 *plain = NULL, *packet = NULL;
+ size_t plain_len = 0, packet_len = 0;
+ struct ft_remote_r1kh *r1kh, *r1kh_wildcard;
+ const u8 *key;
+ size_t key_len;
+ int seq_ret;
+ const u8 *f_nonce, *f_r0kh_id, *f_r1kh_id, *f_s1kh_id, *f_pmk_r0_name;
+ size_t f_nonce_len, f_r0kh_id_len, f_r1kh_id_len, f_s1kh_id_len;
+ size_t f_pmk_r0_name_len;
+ const struct wpa_ft_pmk_r0_sa *r0;
+ int ret;
+ struct tlv_list resp[2];
+ struct tlv_list resp_auth[5];
+ struct ft_rrb_seq f_seq;
wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 pull");
- if (data_len < sizeof(f))
- return -1;
+ RRB_GET_AUTH(FT_RRB_R0KH_ID, r0kh_id, msgtype, -1);
+ wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID", f_r0kh_id, f_r0kh_id_len);
- r1kh = wpa_auth->conf.r1kh_list;
- while (r1kh) {
- if (os_memcmp(r1kh->addr, src_addr, ETH_ALEN) == 0)
- break;
- r1kh = r1kh->next;
+ if (wpa_ft_rrb_check_r0kh(wpa_auth, f_r0kh_id, f_r0kh_id_len)) {
+ wpa_printf(MSG_DEBUG, "FT: R0KH-ID mismatch");
+ goto out;
}
- if (r1kh == NULL) {
- wpa_printf(MSG_DEBUG, "FT: No matching R1KH address found for "
- "PMK-R1 pull source address " MACSTR,
- MAC2STR(src_addr));
- return -1;
+
+ RRB_GET_AUTH(FT_RRB_R1KH_ID, r1kh_id, msgtype, FT_R1KH_ID_LEN);
+ wpa_printf(MSG_DEBUG, "FT: R1KH-ID=" MACSTR, MAC2STR(f_r1kh_id));
+
+ wpa_ft_rrb_lookup_r1kh(wpa_auth, f_r1kh_id, &r1kh, &r1kh_wildcard);
+ if (r1kh) {
+ key = r1kh->key;
+ key_len = sizeof(r1kh->key);
+ } else if (r1kh_wildcard) {
+ wpa_printf(MSG_DEBUG, "FT: Using wildcard R1KH-ID");
+ key = r1kh_wildcard->key;
+ key_len = sizeof(r1kh_wildcard->key);
+ } else {
+ goto out;
}
- crypt = data + offsetof(struct ft_r0kh_r1kh_pull_frame, nonce);
- os_memset(&f, 0, sizeof(f));
- plain = ((u8 *) &f) + offsetof(struct ft_r0kh_r1kh_pull_frame, nonce);
- /* aes_unwrap() does not support inplace decryption, so use a temporary
- * buffer for the data. */
- if (aes_unwrap(r1kh->key, sizeof(r1kh->key),
- (FT_R0KH_R1KH_PULL_DATA_LEN + 7) / 8,
- crypt, plain) < 0) {
- wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 pull "
- "request from " MACSTR, MAC2STR(src_addr));
- return -1;
+ RRB_GET_AUTH(FT_RRB_NONCE, nonce, "pull request", FT_RRB_NONCE_LEN);
+ wpa_hexdump(MSG_DEBUG, "FT: nonce", f_nonce, f_nonce_len);
+
+ seq_ret = FT_RRB_SEQ_DROP;
+ if (r1kh)
+ seq_ret = wpa_ft_rrb_seq_chk(r1kh->seq, src_addr, enc, enc_len,
+ auth, auth_len, msgtype, no_defer);
+ if (!no_defer && r1kh_wildcard &&
+ (!r1kh || os_memcmp(r1kh->addr, src_addr, ETH_ALEN) != 0)) {
+ /* wildcard: r1kh-id unknown or changed addr -> do a seq req */
+ seq_ret = FT_RRB_SEQ_DEFER;
}
- wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - nonce",
- f.nonce, sizeof(f.nonce));
- wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - PMKR0Name",
- f.pmk_r0_name, WPA_PMK_NAME_LEN);
- wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull - R1KH-ID=" MACSTR " S1KH-ID="
- MACSTR, MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id));
-
- os_memset(&resp, 0, sizeof(resp));
- resp.frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB;
- resp.packet_type = FT_PACKET_R0KH_R1KH_RESP;
- resp.data_length = host_to_le16(FT_R0KH_R1KH_RESP_DATA_LEN);
- os_memcpy(resp.ap_address, wpa_auth->addr, ETH_ALEN);
-
- /* aes_wrap() does not support inplace encryption, so use a temporary
- * buffer for the data. */
- os_memcpy(r.nonce, f.nonce, sizeof(f.nonce));
- os_memcpy(r.r1kh_id, f.r1kh_id, FT_R1KH_ID_LEN);
- os_memcpy(r.s1kh_id, f.s1kh_id, ETH_ALEN);
- if (wpa_ft_fetch_pmk_r0(wpa_auth, f.s1kh_id, f.pmk_r0_name, pmk_r0,
- &pairwise) < 0) {
- wpa_printf(MSG_DEBUG, "FT: No matching PMKR0Name found for "
- "PMK-R1 pull");
- return -1;
+ if (seq_ret == FT_RRB_SEQ_DROP)
+ goto out;
+
+ if (wpa_ft_rrb_decrypt(key, key_len, enc, enc_len, auth, auth_len,
+ src_addr, FT_PACKET_R0KH_R1KH_PULL,
+ &plain, &plain_len) < 0)
+ goto out;
+
+ if (!r1kh)
+ r1kh = wpa_ft_rrb_add_r1kh(wpa_auth, r1kh_wildcard, src_addr,
+ f_r1kh_id,
+ wpa_auth->conf.rkh_pos_timeout);
+ if (!r1kh)
+ goto out;
+
+ if (seq_ret == FT_RRB_SEQ_DEFER) {
+ wpa_ft_rrb_seq_req(wpa_auth, r1kh->seq, src_addr, f_r0kh_id,
+ f_r0kh_id_len, f_r1kh_id, key, key_len,
+ enc, enc_len, auth, auth_len,
+ &wpa_ft_rrb_rx_pull);
+ goto out;
}
- wpa_derive_pmk_r1(pmk_r0, f.pmk_r0_name, f.r1kh_id, f.s1kh_id,
- r.pmk_r1, r.pmk_r1_name);
- wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", r.pmk_r1, PMK_LEN);
- wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", r.pmk_r1_name,
- WPA_PMK_NAME_LEN);
- r.pairwise = host_to_le16(pairwise);
- os_memset(r.pad, 0, sizeof(r.pad));
+ wpa_ft_rrb_seq_accept(wpa_auth, r1kh->seq, src_addr, auth, auth_len,
+ msgtype);
+ wpa_ft_rrb_r1kh_replenish(wpa_auth, r1kh,
+ wpa_auth->conf.rkh_pos_timeout);
- if (aes_wrap(r1kh->key, sizeof(r1kh->key),
- (FT_R0KH_R1KH_RESP_DATA_LEN + 7) / 8,
- r.nonce, resp.nonce) < 0) {
- os_memset(pmk_r0, 0, PMK_LEN);
- return -1;
+ RRB_GET(FT_RRB_PMK_R0_NAME, pmk_r0_name, msgtype, WPA_PMK_NAME_LEN);
+ wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name", f_pmk_r0_name,
+ f_pmk_r0_name_len);
+
+ RRB_GET(FT_RRB_S1KH_ID, s1kh_id, msgtype, ETH_ALEN);
+ wpa_printf(MSG_DEBUG, "FT: S1KH-ID=" MACSTR, MAC2STR(f_s1kh_id));
+
+ if (wpa_ft_new_seq(r1kh->seq, &f_seq) < 0) {
+ wpa_printf(MSG_DEBUG, "FT: Failed to get seq num");
+ goto out;
+ }
+
+ resp[0].type = FT_RRB_S1KH_ID;
+ resp[0].len = f_s1kh_id_len;
+ resp[0].data = f_s1kh_id;
+ resp[1].type = FT_RRB_LAST_EMPTY;
+ resp[1].len = 0;
+ resp[1].data = NULL;
+
+ resp_auth[0].type = FT_RRB_NONCE;
+ resp_auth[0].len = f_nonce_len;
+ resp_auth[0].data = f_nonce;
+ resp_auth[1].type = FT_RRB_SEQ;
+ resp_auth[1].len = sizeof(f_seq);
+ resp_auth[1].data = (u8 *) &f_seq;
+ resp_auth[2].type = FT_RRB_R0KH_ID;
+ resp_auth[2].len = f_r0kh_id_len;
+ resp_auth[2].data = f_r0kh_id;
+ resp_auth[3].type = FT_RRB_R1KH_ID;
+ resp_auth[3].len = f_r1kh_id_len;
+ resp_auth[3].data = f_r1kh_id;
+ resp_auth[4].type = FT_RRB_LAST_EMPTY;
+ resp_auth[4].len = 0;
+ resp_auth[4].data = NULL;
+
+ if (wpa_ft_fetch_pmk_r0(wpa_auth, f_s1kh_id, f_pmk_r0_name, &r0) < 0) {
+ wpa_printf(MSG_DEBUG, "FT: No matching PMK-R0-Name found");
+ ret = wpa_ft_rrb_build(key, key_len, resp, NULL, resp_auth,
+ NULL, wpa_auth->addr,
+ FT_PACKET_R0KH_R1KH_RESP,
+ &packet, &packet_len);
+ } else {
+ ret = wpa_ft_rrb_build_r0(key, key_len, resp, r0, f_r1kh_id,
+ f_s1kh_id, resp_auth, wpa_auth->addr,
+ FT_PACKET_R0KH_R1KH_RESP,
+ &packet, &packet_len);
}
- os_memset(pmk_r0, 0, PMK_LEN);
+ if (!ret)
+ wpa_ft_rrb_oui_send(wpa_auth, src_addr,
+ FT_PACKET_R0KH_R1KH_RESP, packet,
+ packet_len);
- wpa_ft_rrb_send(wpa_auth, src_addr, (u8 *) &resp, sizeof(resp));
+out:
+ os_free(plain);
+ os_free(packet);
return 0;
}
-static void ft_pull_resp_cb_finish(void *eloop_ctx, void *timeout_ctx)
+/* @returns 0 on success
+ * -1 on error
+ * -2 if FR_RRB_PAIRWISE is missing
+ */
+static int wpa_ft_rrb_rx_r1(struct wpa_authenticator *wpa_auth,
+ const u8 *src_addr, u8 type,
+ const u8 *enc, size_t enc_len,
+ const u8 *auth, size_t auth_len,
+ const char *msgtype, u8 *s1kh_id_out,
+ int (*cb)(struct wpa_authenticator *wpa_auth,
+ const u8 *src_addr,
+ const u8 *enc, size_t enc_len,
+ const u8 *auth, size_t auth_len,
+ int no_defer))
+{
+ u8 *plain = NULL;
+ size_t plain_len = 0;
+ struct ft_remote_r0kh *r0kh, *r0kh_wildcard;
+ const u8 *key;
+ size_t key_len;
+ int seq_ret;
+ const u8 *f_r1kh_id, *f_s1kh_id, *f_r0kh_id;
+ const u8 *f_pmk_r1_name, *f_pairwise, *f_pmk_r1;
+ const u8 *f_expires_in;
+ size_t f_r1kh_id_len, f_s1kh_id_len, f_r0kh_id_len;
+ const u8 *f_identity, *f_radius_cui;
+ const u8 *f_session_timeout;
+ size_t f_pmk_r1_name_len, f_pairwise_len, f_pmk_r1_len;
+ size_t f_expires_in_len;
+ size_t f_identity_len, f_radius_cui_len;
+ size_t f_session_timeout_len;
+ int pairwise;
+ int ret = -1;
+ int expires_in;
+ int session_timeout;
+ struct vlan_description vlan;
+ size_t pmk_r1_len;
+
+ RRB_GET_AUTH(FT_RRB_R0KH_ID, r0kh_id, msgtype, -1);
+ wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID", f_r0kh_id, f_r0kh_id_len);
+
+ RRB_GET_AUTH(FT_RRB_R1KH_ID, r1kh_id, msgtype, FT_R1KH_ID_LEN);
+ wpa_printf(MSG_DEBUG, "FT: R1KH-ID=" MACSTR, MAC2STR(f_r1kh_id));
+
+ if (wpa_ft_rrb_check_r1kh(wpa_auth, f_r1kh_id)) {
+ wpa_printf(MSG_DEBUG, "FT: R1KH-ID mismatch");
+ goto out;
+ }
+
+ wpa_ft_rrb_lookup_r0kh(wpa_auth, f_r0kh_id, f_r0kh_id_len, &r0kh,
+ &r0kh_wildcard);
+ if (r0kh) {
+ key = r0kh->key;
+ key_len = sizeof(r0kh->key);
+ } else if (r0kh_wildcard) {
+ wpa_printf(MSG_DEBUG, "FT: Using wildcard R0KH-ID");
+ key = r0kh_wildcard->key;
+ key_len = sizeof(r0kh_wildcard->key);
+ } else {
+ goto out;
+ }
+
+ seq_ret = FT_RRB_SEQ_DROP;
+ if (r0kh) {
+ seq_ret = wpa_ft_rrb_seq_chk(r0kh->seq, src_addr, enc, enc_len,
+ auth, auth_len, msgtype,
+ cb ? 0 : 1);
+ }
+ if (cb && r0kh_wildcard &&
+ (!r0kh || os_memcmp(r0kh->addr, src_addr, ETH_ALEN) != 0)) {
+ /* wildcard: r0kh-id unknown or changed addr -> do a seq req */
+ seq_ret = FT_RRB_SEQ_DEFER;
+ }
+
+ if (seq_ret == FT_RRB_SEQ_DROP)
+ goto out;
+
+ if (wpa_ft_rrb_decrypt(key, key_len, enc, enc_len, auth, auth_len,
+ src_addr, type, &plain, &plain_len) < 0)
+ goto out;
+
+ if (!r0kh)
+ r0kh = wpa_ft_rrb_add_r0kh(wpa_auth, r0kh_wildcard, src_addr,
+ f_r0kh_id, f_r0kh_id_len,
+ wpa_auth->conf.rkh_pos_timeout);
+ if (!r0kh)
+ goto out;
+
+ if (seq_ret == FT_RRB_SEQ_DEFER) {
+ wpa_ft_rrb_seq_req(wpa_auth, r0kh->seq, src_addr, f_r0kh_id,
+ f_r0kh_id_len, f_r1kh_id, key, key_len,
+ enc, enc_len, auth, auth_len, cb);
+ goto out;
+ }
+
+ wpa_ft_rrb_seq_accept(wpa_auth, r0kh->seq, src_addr, auth, auth_len,
+ msgtype);
+ wpa_ft_rrb_r0kh_replenish(wpa_auth, r0kh,
+ wpa_auth->conf.rkh_pos_timeout);
+
+ RRB_GET(FT_RRB_S1KH_ID, s1kh_id, msgtype, ETH_ALEN);
+ wpa_printf(MSG_DEBUG, "FT: S1KH-ID=" MACSTR, MAC2STR(f_s1kh_id));
+
+ if (s1kh_id_out)
+ os_memcpy(s1kh_id_out, f_s1kh_id, ETH_ALEN);
+
+ ret = -2;
+ RRB_GET(FT_RRB_PAIRWISE, pairwise, msgtype, sizeof(le16));
+ wpa_hexdump(MSG_DEBUG, "FT: pairwise", f_pairwise, f_pairwise_len);
+
+ ret = -1;
+ RRB_GET(FT_RRB_PMK_R1_NAME, pmk_r1_name, msgtype, WPA_PMK_NAME_LEN);
+ wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name",
+ f_pmk_r1_name, WPA_PMK_NAME_LEN);
+
+ pmk_r1_len = PMK_LEN;
+ if (wpa_ft_rrb_get_tlv(plain, plain_len, FT_RRB_PMK_R1, &f_pmk_r1_len,
+ &f_pmk_r1) == 0 &&
+ (f_pmk_r1_len == PMK_LEN || f_pmk_r1_len == SHA384_MAC_LEN))
+ pmk_r1_len = f_pmk_r1_len;
+ RRB_GET(FT_RRB_PMK_R1, pmk_r1, msgtype, pmk_r1_len);
+ wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", f_pmk_r1, pmk_r1_len);
+
+ pairwise = WPA_GET_LE16(f_pairwise);
+
+ RRB_GET_OPTIONAL(FT_RRB_EXPIRES_IN, expires_in, msgtype,
+ sizeof(le16));
+ if (f_expires_in)
+ expires_in = WPA_GET_LE16(f_expires_in);
+ else
+ expires_in = 0;
+
+ wpa_printf(MSG_DEBUG, "FT: PMK-R1 %s - expires_in=%d", msgtype,
+ expires_in);
+
+ if (wpa_ft_rrb_get_tlv_vlan(plain, plain_len, &vlan) < 0) {
+ wpa_printf(MSG_DEBUG, "FT: Cannot parse vlan");
+ wpa_ft_rrb_dump(plain, plain_len);
+ goto out;
+ }
+
+ wpa_printf(MSG_DEBUG, "FT: vlan %d%s",
+ le_to_host16(vlan.untagged), vlan.tagged[0] ? "+" : "");
+
+ RRB_GET_OPTIONAL(FT_RRB_IDENTITY, identity, msgtype, -1);
+ if (f_identity)
+ wpa_hexdump_ascii(MSG_DEBUG, "FT: Identity", f_identity,
+ f_identity_len);
+
+ RRB_GET_OPTIONAL(FT_RRB_RADIUS_CUI, radius_cui, msgtype, -1);
+ if (f_radius_cui)
+ wpa_hexdump_ascii(MSG_DEBUG, "FT: CUI", f_radius_cui,
+ f_radius_cui_len);
+
+ RRB_GET_OPTIONAL(FT_RRB_SESSION_TIMEOUT, session_timeout, msgtype,
+ sizeof(le32));
+ if (f_session_timeout)
+ session_timeout = WPA_GET_LE32(f_session_timeout);
+ else
+ session_timeout = 0;
+ wpa_printf(MSG_DEBUG, "FT: session_timeout %d", session_timeout);
+
+ if (wpa_ft_store_pmk_r1(wpa_auth, f_s1kh_id, f_pmk_r1, pmk_r1_len,
+ f_pmk_r1_name,
+ pairwise, &vlan, expires_in, session_timeout,
+ f_identity, f_identity_len, f_radius_cui,
+ f_radius_cui_len) < 0)
+ goto out;
+
+ ret = 0;
+out:
+ if (plain) {
+ os_memset(plain, 0, plain_len);
+ os_free(plain);
+ }
+
+ return ret;
+
+}
+
+
+static void ft_finish_pull(struct wpa_state_machine *sm)
{
- struct wpa_state_machine *sm = eloop_ctx;
int res;
u8 *resp_ies;
size_t resp_ies_len;
u16 status;
+ if (!sm->ft_pending_cb || !sm->ft_pending_req_ies)
+ return;
+
res = wpa_ft_process_auth_req(sm, wpabuf_head(sm->ft_pending_req_ies),
wpabuf_len(sm->ft_pending_req_ies),
&resp_ies, &resp_ies_len);
+ if (res < 0) {
+ /* this loop is broken by ft_pending_pull_left_retries */
+ wpa_printf(MSG_DEBUG,
+ "FT: Callback postponed until response is available");
+ return;
+ }
wpabuf_free(sm->ft_pending_req_ies);
sm->ft_pending_req_ies = NULL;
- if (res < 0)
- res = WLAN_STATUS_UNSPECIFIED_FAILURE;
status = res;
wpa_printf(MSG_DEBUG, "FT: Postponed auth callback result for " MACSTR
" - status %u", MAC2STR(sm->addr), status);
@@ -1435,171 +3926,383 @@ static void ft_pull_resp_cb_finish(void *eloop_ctx, void *timeout_ctx)
}
-static int ft_pull_resp_cb(struct wpa_state_machine *sm, void *ctx)
+struct ft_get_sta_ctx {
+ const u8 *nonce;
+ const u8 *s1kh_id;
+ struct wpa_state_machine *sm;
+};
+
+
+static int ft_get_sta_cb(struct wpa_state_machine *sm, void *ctx)
{
- struct ft_r0kh_r1kh_resp_frame *frame = ctx;
+ struct ft_get_sta_ctx *info = ctx;
- if (os_memcmp(frame->s1kh_id, sm->addr, ETH_ALEN) != 0)
- return 0;
- if (os_memcmp(frame->nonce, sm->ft_pending_pull_nonce,
- FT_R0KH_R1KH_PULL_NONCE_LEN) != 0)
- return 0;
- if (sm->ft_pending_cb == NULL || sm->ft_pending_req_ies == NULL)
+ if ((info->s1kh_id &&
+ os_memcmp(info->s1kh_id, sm->addr, ETH_ALEN) != 0) ||
+ os_memcmp(info->nonce, sm->ft_pending_pull_nonce,
+ FT_RRB_NONCE_LEN) != 0 ||
+ sm->ft_pending_cb == NULL || sm->ft_pending_req_ies == NULL)
return 0;
- wpa_printf(MSG_DEBUG, "FT: Response to a pending pull request for "
- MACSTR " - process from timeout", MAC2STR(sm->addr));
- eloop_register_timeout(0, 0, ft_pull_resp_cb_finish, sm, NULL);
+ info->sm = sm;
+
return 1;
}
static int wpa_ft_rrb_rx_resp(struct wpa_authenticator *wpa_auth,
const u8 *src_addr,
- const u8 *data, size_t data_len)
+ const u8 *enc, size_t enc_len,
+ const u8 *auth, size_t auth_len,
+ int no_defer)
{
- struct ft_r0kh_r1kh_resp_frame f;
- const u8 *crypt;
- u8 *plain;
- struct ft_remote_r0kh *r0kh;
- int pairwise, res;
+ const char *msgtype = "pull response";
+ int nak, ret = -1;
+ struct ft_get_sta_ctx ctx;
+ u8 s1kh_id[ETH_ALEN];
+ const u8 *f_nonce;
+ size_t f_nonce_len;
wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 pull response");
- if (data_len < sizeof(f))
- return -1;
+ RRB_GET_AUTH(FT_RRB_NONCE, nonce, msgtype, FT_RRB_NONCE_LEN);
+ wpa_hexdump(MSG_DEBUG, "FT: nonce", f_nonce, f_nonce_len);
- r0kh = wpa_auth->conf.r0kh_list;
- while (r0kh) {
- if (os_memcmp(r0kh->addr, src_addr, ETH_ALEN) == 0)
- break;
- r0kh = r0kh->next;
- }
- if (r0kh == NULL) {
- wpa_printf(MSG_DEBUG, "FT: No matching R0KH address found for "
- "PMK-R0 pull response source address " MACSTR,
- MAC2STR(src_addr));
+ os_memset(&ctx, 0, sizeof(ctx));
+ ctx.nonce = f_nonce;
+ if (!wpa_auth_for_each_sta(wpa_auth, ft_get_sta_cb, &ctx)) {
+ /* nonce not found */
+ wpa_printf(MSG_DEBUG, "FT: Invalid nonce");
return -1;
}
- crypt = data + offsetof(struct ft_r0kh_r1kh_resp_frame, nonce);
- os_memset(&f, 0, sizeof(f));
- plain = ((u8 *) &f) + offsetof(struct ft_r0kh_r1kh_resp_frame, nonce);
- /* aes_unwrap() does not support inplace decryption, so use a temporary
- * buffer for the data. */
- if (aes_unwrap(r0kh->key, sizeof(r0kh->key),
- (FT_R0KH_R1KH_RESP_DATA_LEN + 7) / 8,
- crypt, plain) < 0) {
- wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 pull "
- "response from " MACSTR, MAC2STR(src_addr));
- return -1;
+ ret = wpa_ft_rrb_rx_r1(wpa_auth, src_addr, FT_PACKET_R0KH_R1KH_RESP,
+ enc, enc_len, auth, auth_len, msgtype, s1kh_id,
+ no_defer ? NULL : &wpa_ft_rrb_rx_resp);
+ if (ret == -2) {
+ ret = 0;
+ nak = 1;
+ } else {
+ nak = 0;
}
-
- if (os_memcmp_const(f.r1kh_id, wpa_auth->conf.r1_key_holder,
- FT_R1KH_ID_LEN) != 0) {
- wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull response did not use a "
- "matching R1KH-ID");
+ if (ret < 0)
return -1;
- }
-
- pairwise = le_to_host16(f.pairwise);
- wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - nonce",
- f.nonce, sizeof(f.nonce));
- wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull - R1KH-ID=" MACSTR " S1KH-ID="
- MACSTR " pairwise=0x%x",
- MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id), pairwise);
- wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1 pull - PMK-R1",
- f.pmk_r1, PMK_LEN);
- wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - PMKR1Name",
- f.pmk_r1_name, WPA_PMK_NAME_LEN);
- res = wpa_ft_store_pmk_r1(wpa_auth, f.s1kh_id, f.pmk_r1, f.pmk_r1_name,
- pairwise);
- wpa_printf(MSG_DEBUG, "FT: Look for pending pull request");
- wpa_auth_for_each_sta(wpa_auth, ft_pull_resp_cb, &f);
- os_memset(f.pmk_r1, 0, PMK_LEN);
+ ctx.s1kh_id = s1kh_id;
+ if (wpa_auth_for_each_sta(wpa_auth, ft_get_sta_cb, &ctx)) {
+ wpa_printf(MSG_DEBUG,
+ "FT: Response to a pending pull request for " MACSTR,
+ MAC2STR(ctx.sm->addr));
+ eloop_cancel_timeout(wpa_ft_expire_pull, ctx.sm, NULL);
+ if (nak)
+ ctx.sm->ft_pending_pull_left_retries = 0;
+ ft_finish_pull(ctx.sm);
+ }
- return res ? 0 : -1;
+out:
+ return ret;
}
static int wpa_ft_rrb_rx_push(struct wpa_authenticator *wpa_auth,
const u8 *src_addr,
- const u8 *data, size_t data_len)
+ const u8 *enc, size_t enc_len,
+ const u8 *auth, size_t auth_len, int no_defer)
{
- struct ft_r0kh_r1kh_push_frame f;
- const u8 *crypt;
- u8 *plain;
- struct ft_remote_r0kh *r0kh;
- struct os_time now;
- os_time_t tsend;
- int pairwise;
+ const char *msgtype = "push";
wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 push");
- if (data_len < sizeof(f))
+ if (wpa_ft_rrb_rx_r1(wpa_auth, src_addr, FT_PACKET_R0KH_R1KH_PUSH,
+ enc, enc_len, auth, auth_len, msgtype, NULL,
+ no_defer ? NULL : wpa_ft_rrb_rx_push) < 0)
return -1;
- r0kh = wpa_auth->conf.r0kh_list;
- while (r0kh) {
- if (os_memcmp(r0kh->addr, src_addr, ETH_ALEN) == 0)
- break;
- r0kh = r0kh->next;
+ return 0;
+}
+
+
+static int wpa_ft_rrb_rx_seq(struct wpa_authenticator *wpa_auth,
+ const u8 *src_addr, int type,
+ const u8 *enc, size_t enc_len,
+ const u8 *auth, size_t auth_len,
+ struct ft_remote_seq **rkh_seq,
+ u8 **key, size_t *key_len,
+ struct ft_remote_r0kh **r0kh_out,
+ struct ft_remote_r1kh **r1kh_out,
+ struct ft_remote_r0kh **r0kh_wildcard_out,
+ struct ft_remote_r1kh **r1kh_wildcard_out)
+{
+ struct ft_remote_r0kh *r0kh = NULL;
+ struct ft_remote_r1kh *r1kh = NULL;
+ const u8 *f_r0kh_id, *f_r1kh_id;
+ size_t f_r0kh_id_len, f_r1kh_id_len;
+ int to_r0kh, to_r1kh;
+ u8 *plain = NULL;
+ size_t plain_len = 0;
+ struct ft_remote_r0kh *r0kh_wildcard;
+ struct ft_remote_r1kh *r1kh_wildcard;
+
+ RRB_GET_AUTH(FT_RRB_R0KH_ID, r0kh_id, "seq", -1);
+ RRB_GET_AUTH(FT_RRB_R1KH_ID, r1kh_id, "seq", FT_R1KH_ID_LEN);
+
+ to_r0kh = !wpa_ft_rrb_check_r0kh(wpa_auth, f_r0kh_id, f_r0kh_id_len);
+ to_r1kh = !wpa_ft_rrb_check_r1kh(wpa_auth, f_r1kh_id);
+
+ if (to_r0kh && to_r1kh) {
+ wpa_printf(MSG_DEBUG, "FT: seq - local R0KH-ID and R1KH-ID");
+ goto out;
}
- if (r0kh == NULL) {
- wpa_printf(MSG_DEBUG, "FT: No matching R0KH address found for "
- "PMK-R0 push source address " MACSTR,
- MAC2STR(src_addr));
- return -1;
+
+ if (!to_r0kh && !to_r1kh) {
+ wpa_printf(MSG_DEBUG, "FT: seq - remote R0KH-ID and R1KH-ID");
+ goto out;
}
- crypt = data + offsetof(struct ft_r0kh_r1kh_push_frame, timestamp);
- os_memset(&f, 0, sizeof(f));
- plain = ((u8 *) &f) + offsetof(struct ft_r0kh_r1kh_push_frame,
- timestamp);
- /* aes_unwrap() does not support inplace decryption, so use a temporary
- * buffer for the data. */
- if (aes_unwrap(r0kh->key, sizeof(r0kh->key),
- (FT_R0KH_R1KH_PUSH_DATA_LEN + 7) / 8,
- crypt, plain) < 0) {
- wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 push from "
- MACSTR, MAC2STR(src_addr));
- return -1;
+ if (!to_r0kh) {
+ wpa_ft_rrb_lookup_r0kh(wpa_auth, f_r0kh_id, f_r0kh_id_len,
+ &r0kh, &r0kh_wildcard);
+ if (!r0kh_wildcard &&
+ (!r0kh || os_memcmp(r0kh->addr, src_addr, ETH_ALEN) != 0)) {
+ wpa_hexdump(MSG_DEBUG, "FT: Did not find R0KH-ID",
+ f_r0kh_id, f_r0kh_id_len);
+ goto out;
+ }
+ if (r0kh) {
+ *key = r0kh->key;
+ *key_len = sizeof(r0kh->key);
+ } else {
+ *key = r0kh_wildcard->key;
+ *key_len = sizeof(r0kh_wildcard->key);
+ }
}
- os_get_time(&now);
- tsend = WPA_GET_LE32(f.timestamp);
- if ((now.sec > tsend && now.sec - tsend > 60) ||
- (now.sec < tsend && tsend - now.sec > 60)) {
- wpa_printf(MSG_DEBUG, "FT: PMK-R1 push did not have a valid "
- "timestamp: sender time %d own time %d\n",
- (int) tsend, (int) now.sec);
- return -1;
+ if (!to_r1kh) {
+ wpa_ft_rrb_lookup_r1kh(wpa_auth, f_r1kh_id, &r1kh,
+ &r1kh_wildcard);
+ if (!r1kh_wildcard &&
+ (!r1kh || os_memcmp(r1kh->addr, src_addr, ETH_ALEN) != 0)) {
+ wpa_hexdump(MSG_DEBUG, "FT: Did not find R1KH-ID",
+ f_r1kh_id, FT_R1KH_ID_LEN);
+ goto out;
+ }
+ if (r1kh) {
+ *key = r1kh->key;
+ *key_len = sizeof(r1kh->key);
+ } else {
+ *key = r1kh_wildcard->key;
+ *key_len = sizeof(r1kh_wildcard->key);
+ }
}
- if (os_memcmp_const(f.r1kh_id, wpa_auth->conf.r1_key_holder,
- FT_R1KH_ID_LEN) != 0) {
- wpa_printf(MSG_DEBUG, "FT: PMK-R1 push did not use a matching "
- "R1KH-ID (received " MACSTR " own " MACSTR ")",
- MAC2STR(f.r1kh_id),
- MAC2STR(wpa_auth->conf.r1_key_holder));
- return -1;
+ if (wpa_ft_rrb_decrypt(*key, *key_len, enc, enc_len, auth, auth_len,
+ src_addr, type, &plain, &plain_len) < 0)
+ goto out;
+
+ os_free(plain);
+
+ if (!to_r0kh) {
+ if (!r0kh)
+ r0kh = wpa_ft_rrb_add_r0kh(wpa_auth, r0kh_wildcard,
+ src_addr, f_r0kh_id,
+ f_r0kh_id_len,
+ ftRRBseqTimeout);
+ if (!r0kh)
+ goto out;
+
+ wpa_ft_rrb_r0kh_replenish(wpa_auth, r0kh, ftRRBseqTimeout);
+ *rkh_seq = r0kh->seq;
+ if (r0kh_out)
+ *r0kh_out = r0kh;
+ if (r0kh_wildcard_out)
+ *r0kh_wildcard_out = r0kh_wildcard;
+ }
+
+ if (!to_r1kh) {
+ if (!r1kh)
+ r1kh = wpa_ft_rrb_add_r1kh(wpa_auth, r1kh_wildcard,
+ src_addr, f_r1kh_id,
+ ftRRBseqTimeout);
+ if (!r1kh)
+ goto out;
+
+ wpa_ft_rrb_r1kh_replenish(wpa_auth, r1kh, ftRRBseqTimeout);
+ *rkh_seq = r1kh->seq;
+ if (r1kh_out)
+ *r1kh_out = r1kh;
+ if (r1kh_wildcard_out)
+ *r1kh_wildcard_out = r1kh_wildcard;
}
- pairwise = le_to_host16(f.pairwise);
- wpa_printf(MSG_DEBUG, "FT: PMK-R1 push - R1KH-ID=" MACSTR " S1KH-ID="
- MACSTR " pairwise=0x%x",
- MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id), pairwise);
- wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1 push - PMK-R1",
- f.pmk_r1, PMK_LEN);
- wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 push - PMKR1Name",
- f.pmk_r1_name, WPA_PMK_NAME_LEN);
+ return 0;
+out:
+ return -1;
+}
+
- wpa_ft_store_pmk_r1(wpa_auth, f.s1kh_id, f.pmk_r1, f.pmk_r1_name,
- pairwise);
- os_memset(f.pmk_r1, 0, PMK_LEN);
+static int wpa_ft_rrb_rx_seq_req(struct wpa_authenticator *wpa_auth,
+ const u8 *src_addr,
+ const u8 *enc, size_t enc_len,
+ const u8 *auth, size_t auth_len,
+ int no_defer)
+{
+ int ret = -1;
+ struct ft_rrb_seq f_seq;
+ const u8 *f_nonce, *f_r0kh_id, *f_r1kh_id;
+ size_t f_nonce_len, f_r0kh_id_len, f_r1kh_id_len;
+ struct ft_remote_seq *rkh_seq = NULL;
+ u8 *packet = NULL, *key = NULL;
+ size_t packet_len = 0, key_len = 0;
+ struct tlv_list seq_resp_auth[5];
+
+ wpa_printf(MSG_DEBUG, "FT: Received sequence number request");
+
+ if (wpa_ft_rrb_rx_seq(wpa_auth, src_addr, FT_PACKET_R0KH_R1KH_SEQ_REQ,
+ enc, enc_len, auth, auth_len, &rkh_seq, &key,
+ &key_len, NULL, NULL, NULL, NULL) < 0)
+ goto out;
+
+ RRB_GET_AUTH(FT_RRB_NONCE, nonce, "seq request", FT_RRB_NONCE_LEN);
+ wpa_hexdump(MSG_DEBUG, "FT: seq request - nonce", f_nonce, f_nonce_len);
+
+ RRB_GET_AUTH(FT_RRB_R0KH_ID, r0kh_id, "seq", -1);
+ RRB_GET_AUTH(FT_RRB_R1KH_ID, r1kh_id, "seq", FT_R1KH_ID_LEN);
+
+ if (wpa_ft_new_seq(rkh_seq, &f_seq) < 0) {
+ wpa_printf(MSG_DEBUG, "FT: Failed to get seq num");
+ goto out;
+ }
+
+ seq_resp_auth[0].type = FT_RRB_NONCE;
+ seq_resp_auth[0].len = f_nonce_len;
+ seq_resp_auth[0].data = f_nonce;
+ seq_resp_auth[1].type = FT_RRB_SEQ;
+ seq_resp_auth[1].len = sizeof(f_seq);
+ seq_resp_auth[1].data = (u8 *) &f_seq;
+ seq_resp_auth[2].type = FT_RRB_R0KH_ID;
+ seq_resp_auth[2].len = f_r0kh_id_len;
+ seq_resp_auth[2].data = f_r0kh_id;
+ seq_resp_auth[3].type = FT_RRB_R1KH_ID;
+ seq_resp_auth[3].len = FT_R1KH_ID_LEN;
+ seq_resp_auth[3].data = f_r1kh_id;
+ seq_resp_auth[4].type = FT_RRB_LAST_EMPTY;
+ seq_resp_auth[4].len = 0;
+ seq_resp_auth[4].data = NULL;
+
+ if (wpa_ft_rrb_build(key, key_len, NULL, NULL, seq_resp_auth, NULL,
+ wpa_auth->addr, FT_PACKET_R0KH_R1KH_SEQ_RESP,
+ &packet, &packet_len) < 0)
+ goto out;
+
+ wpa_ft_rrb_oui_send(wpa_auth, src_addr,
+ FT_PACKET_R0KH_R1KH_SEQ_RESP, packet,
+ packet_len);
+
+out:
+ os_free(packet);
+
+ return ret;
+}
+
+
+static int wpa_ft_rrb_rx_seq_resp(struct wpa_authenticator *wpa_auth,
+ const u8 *src_addr,
+ const u8 *enc, size_t enc_len,
+ const u8 *auth, size_t auth_len,
+ int no_defer)
+{
+ u8 *key = NULL;
+ size_t key_len = 0;
+ struct ft_remote_r0kh *r0kh = NULL, *r0kh_wildcard = NULL;
+ struct ft_remote_r1kh *r1kh = NULL, *r1kh_wildcard = NULL;
+ const u8 *f_nonce, *f_seq;
+ size_t f_nonce_len, f_seq_len;
+ struct ft_remote_seq *rkh_seq = NULL;
+ struct ft_remote_item *item;
+ struct os_reltime now, now_remote;
+ int seq_ret, found;
+ const struct ft_rrb_seq *msg_both;
+ u32 msg_dom, msg_seq;
+
+ wpa_printf(MSG_DEBUG, "FT: Received sequence number response");
+
+ if (wpa_ft_rrb_rx_seq(wpa_auth, src_addr, FT_PACKET_R0KH_R1KH_SEQ_RESP,
+ enc, enc_len, auth, auth_len, &rkh_seq, &key,
+ &key_len, &r0kh, &r1kh, &r0kh_wildcard,
+ &r1kh_wildcard) < 0)
+ goto out;
+
+ RRB_GET_AUTH(FT_RRB_NONCE, nonce, "seq response", FT_RRB_NONCE_LEN);
+ wpa_hexdump(MSG_DEBUG, "FT: seq response - nonce", f_nonce,
+ f_nonce_len);
+
+ found = 0;
+ dl_list_for_each(item, &rkh_seq->rx.queue, struct ft_remote_item,
+ list) {
+ if (os_memcmp_const(f_nonce, item->nonce,
+ FT_RRB_NONCE_LEN) != 0 ||
+ os_get_reltime(&now) < 0 ||
+ os_reltime_expired(&now, &item->nonce_ts, ftRRBseqTimeout))
+ continue;
+
+ found = 1;
+ break;
+ }
+ if (!found) {
+ wpa_printf(MSG_DEBUG, "FT: seq response - bad nonce");
+ goto out;
+ }
+
+ if (r0kh) {
+ wpa_ft_rrb_r0kh_replenish(wpa_auth, r0kh,
+ wpa_auth->conf.rkh_pos_timeout);
+ if (r0kh_wildcard)
+ os_memcpy(r0kh->addr, src_addr, ETH_ALEN);
+ }
+
+ if (r1kh) {
+ wpa_ft_rrb_r1kh_replenish(wpa_auth, r1kh,
+ wpa_auth->conf.rkh_pos_timeout);
+ if (r1kh_wildcard)
+ os_memcpy(r1kh->addr, src_addr, ETH_ALEN);
+ }
+
+ seq_ret = wpa_ft_rrb_seq_chk(rkh_seq, src_addr, enc, enc_len, auth,
+ auth_len, "seq response", 1);
+ if (seq_ret == FT_RRB_SEQ_OK) {
+ wpa_printf(MSG_DEBUG, "FT: seq response - valid seq number");
+ wpa_ft_rrb_seq_accept(wpa_auth, rkh_seq, src_addr, auth,
+ auth_len, "seq response");
+ } else {
+ wpa_printf(MSG_DEBUG, "FT: seq response - reset seq number");
+
+ RRB_GET_AUTH(FT_RRB_SEQ, seq, "seq response",
+ sizeof(*msg_both));
+ msg_both = (const struct ft_rrb_seq *) f_seq;
+
+ msg_dom = le_to_host32(msg_both->dom);
+ msg_seq = le_to_host32(msg_both->seq);
+ now_remote.sec = le_to_host32(msg_both->ts);
+ now_remote.usec = 0;
+
+ rkh_seq->rx.num_last = 2;
+ rkh_seq->rx.dom = msg_dom;
+ rkh_seq->rx.offsetidx = 0;
+ /* Accept some older, possibly cached packets as well */
+ rkh_seq->rx.last[0] = msg_seq - FT_REMOTE_SEQ_BACKLOG -
+ dl_list_len(&rkh_seq->rx.queue);
+ rkh_seq->rx.last[1] = msg_seq;
+
+ /* local time - offset = remote time
+ * <=> local time - remote time = offset */
+ os_reltime_sub(&now, &now_remote, &rkh_seq->rx.time_offset);
+ }
+
+ wpa_ft_rrb_seq_flush(wpa_auth, rkh_seq, 1);
return 0;
+out:
+ return -1;
}
@@ -1644,13 +4347,6 @@ int wpa_ft_rrb_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr,
return -1;
}
- if (frame->packet_type == FT_PACKET_R0KH_R1KH_PULL)
- return wpa_ft_rrb_rx_pull(wpa_auth, src_addr, data, data_len);
- if (frame->packet_type == FT_PACKET_R0KH_R1KH_RESP)
- return wpa_ft_rrb_rx_resp(wpa_auth, src_addr, data, data_len);
- if (frame->packet_type == FT_PACKET_R0KH_R1KH_PUSH)
- return wpa_ft_rrb_rx_push(wpa_auth, src_addr, data, data_len);
-
wpa_hexdump(MSG_MSGDUMP, "FT: RRB - FT Action frame", pos, alen);
if (alen < 1 + 1 + 2 * ETH_ALEN) {
@@ -1728,65 +4424,140 @@ int wpa_ft_rrb_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr,
}
-static void wpa_ft_generate_pmk_r1(struct wpa_authenticator *wpa_auth,
- struct wpa_ft_pmk_r0_sa *pmk_r0,
- struct ft_remote_r1kh *r1kh,
- const u8 *s1kh_id, int pairwise)
-{
- struct ft_r0kh_r1kh_push_frame frame, f;
- struct os_time now;
- const u8 *plain;
- u8 *crypt;
-
- os_memset(&frame, 0, sizeof(frame));
- frame.frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB;
- frame.packet_type = FT_PACKET_R0KH_R1KH_PUSH;
- frame.data_length = host_to_le16(FT_R0KH_R1KH_PUSH_DATA_LEN);
- os_memcpy(frame.ap_address, wpa_auth->addr, ETH_ALEN);
-
- /* aes_wrap() does not support inplace encryption, so use a temporary
- * buffer for the data. */
- os_memcpy(f.r1kh_id, r1kh->id, FT_R1KH_ID_LEN);
- os_memcpy(f.s1kh_id, s1kh_id, ETH_ALEN);
- os_memcpy(f.pmk_r0_name, pmk_r0->pmk_r0_name, WPA_PMK_NAME_LEN);
- wpa_derive_pmk_r1(pmk_r0->pmk_r0, pmk_r0->pmk_r0_name, r1kh->id,
- s1kh_id, f.pmk_r1, f.pmk_r1_name);
- wpa_printf(MSG_DEBUG, "FT: R1KH-ID " MACSTR, MAC2STR(r1kh->id));
- wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", f.pmk_r1, PMK_LEN);
- wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", f.pmk_r1_name,
- WPA_PMK_NAME_LEN);
- os_get_time(&now);
- WPA_PUT_LE32(f.timestamp, now.sec);
- f.pairwise = host_to_le16(pairwise);
- os_memset(f.pad, 0, sizeof(f.pad));
- plain = ((const u8 *) &f) + offsetof(struct ft_r0kh_r1kh_push_frame,
- timestamp);
- crypt = ((u8 *) &frame) + offsetof(struct ft_r0kh_r1kh_push_frame,
- timestamp);
- if (aes_wrap(r1kh->key, sizeof(r1kh->key),
- (FT_R0KH_R1KH_PUSH_DATA_LEN + 7) / 8,
- plain, crypt) < 0)
+void wpa_ft_rrb_oui_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr,
+ const u8 *dst_addr, u8 oui_suffix, const u8 *data,
+ size_t data_len)
+{
+ const u8 *auth, *enc;
+ size_t alen, elen;
+ int no_defer = 0;
+
+ wpa_printf(MSG_DEBUG, "FT: RRB-OUI received frame from remote AP "
+ MACSTR, MAC2STR(src_addr));
+ wpa_printf(MSG_DEBUG, "FT: RRB-OUI frame - oui_suffix=%d", oui_suffix);
+ wpa_hexdump(MSG_MSGDUMP, "FT: RRB frame payload", data, data_len);
+
+ if (is_multicast_ether_addr(src_addr)) {
+ wpa_printf(MSG_DEBUG,
+ "FT: RRB-OUI received frame from multicast address "
+ MACSTR, MAC2STR(src_addr));
+ return;
+ }
+
+ if (is_multicast_ether_addr(dst_addr)) {
+ wpa_printf(MSG_DEBUG,
+ "FT: RRB-OUI received frame from remote AP " MACSTR
+ " to multicast address " MACSTR,
+ MAC2STR(src_addr), MAC2STR(dst_addr));
+ no_defer = 1;
+ }
+
+ if (data_len < sizeof(u16)) {
+ wpa_printf(MSG_DEBUG, "FT: RRB-OUI frame too short");
return;
+ }
+
+ alen = WPA_GET_LE16(data);
+ if (data_len < sizeof(u16) + alen) {
+ wpa_printf(MSG_DEBUG, "FT: RRB-OUI frame too short");
+ return;
+ }
+
+ auth = data + sizeof(u16);
+ wpa_hexdump(MSG_MSGDUMP, "FT: Authenticated payload", auth, alen);
+ enc = data + sizeof(u16) + alen;
+ elen = data_len - sizeof(u16) - alen;
+ wpa_hexdump(MSG_MSGDUMP, "FT: Encrypted payload", enc, elen);
+
+ switch (oui_suffix) {
+ case FT_PACKET_R0KH_R1KH_PULL:
+ wpa_ft_rrb_rx_pull(wpa_auth, src_addr, enc, elen, auth, alen,
+ no_defer);
+ break;
+ case FT_PACKET_R0KH_R1KH_RESP:
+ wpa_ft_rrb_rx_resp(wpa_auth, src_addr, enc, elen, auth, alen,
+ no_defer);
+ break;
+ case FT_PACKET_R0KH_R1KH_PUSH:
+ wpa_ft_rrb_rx_push(wpa_auth, src_addr, enc, elen, auth, alen,
+ no_defer);
+ break;
+ case FT_PACKET_R0KH_R1KH_SEQ_REQ:
+ wpa_ft_rrb_rx_seq_req(wpa_auth, src_addr, enc, elen, auth, alen,
+ no_defer);
+ break;
+ case FT_PACKET_R0KH_R1KH_SEQ_RESP:
+ wpa_ft_rrb_rx_seq_resp(wpa_auth, src_addr, enc, elen, auth,
+ alen, no_defer);
+ break;
+ }
+}
- wpa_ft_rrb_send(wpa_auth, r1kh->addr, (u8 *) &frame, sizeof(frame));
+
+static int wpa_ft_generate_pmk_r1(struct wpa_authenticator *wpa_auth,
+ struct wpa_ft_pmk_r0_sa *pmk_r0,
+ struct ft_remote_r1kh *r1kh,
+ const u8 *s1kh_id)
+{
+ u8 *packet;
+ size_t packet_len;
+ struct ft_rrb_seq f_seq;
+ struct tlv_list push[] = {
+ { .type = FT_RRB_S1KH_ID, .len = ETH_ALEN,
+ .data = s1kh_id },
+ { .type = FT_RRB_PMK_R0_NAME, .len = WPA_PMK_NAME_LEN,
+ .data = pmk_r0->pmk_r0_name },
+ { .type = FT_RRB_LAST_EMPTY, .len = 0, .data = NULL },
+ };
+ struct tlv_list push_auth[] = {
+ { .type = FT_RRB_SEQ, .len = sizeof(f_seq),
+ .data = (u8 *) &f_seq },
+ { .type = FT_RRB_R0KH_ID,
+ .len = wpa_auth->conf.r0_key_holder_len,
+ .data = wpa_auth->conf.r0_key_holder },
+ { .type = FT_RRB_R1KH_ID, .len = FT_R1KH_ID_LEN,
+ .data = r1kh->id },
+ { .type = FT_RRB_LAST_EMPTY, .len = 0, .data = NULL },
+ };
+
+ if (wpa_ft_new_seq(r1kh->seq, &f_seq) < 0) {
+ wpa_printf(MSG_DEBUG, "FT: Failed to get seq num");
+ return -1;
+ }
+
+ if (wpa_ft_rrb_build_r0(r1kh->key, sizeof(r1kh->key), push, pmk_r0,
+ r1kh->id, s1kh_id, push_auth, wpa_auth->addr,
+ FT_PACKET_R0KH_R1KH_PUSH,
+ &packet, &packet_len) < 0)
+ return -1;
+
+ wpa_ft_rrb_oui_send(wpa_auth, r1kh->addr, FT_PACKET_R0KH_R1KH_PUSH,
+ packet, packet_len);
+
+ os_free(packet);
+ return 0;
}
void wpa_ft_push_pmk_r1(struct wpa_authenticator *wpa_auth, const u8 *addr)
{
- struct wpa_ft_pmk_r0_sa *r0;
+ struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache;
+ struct wpa_ft_pmk_r0_sa *r0, *r0found = NULL;
struct ft_remote_r1kh *r1kh;
if (!wpa_auth->conf.pmk_r1_push)
return;
+ if (!wpa_auth->conf.r1kh_list)
+ return;
- r0 = wpa_auth->ft_pmk_cache->pmk_r0;
- while (r0) {
- if (os_memcmp(r0->spa, addr, ETH_ALEN) == 0)
+ dl_list_for_each(r0, &cache->pmk_r0, struct wpa_ft_pmk_r0_sa, list) {
+ if (os_memcmp(r0->spa, addr, ETH_ALEN) == 0) {
+ r0found = r0;
break;
- r0 = r0->next;
+ }
}
+ r0 = r0found;
if (r0 == NULL || r0->pmk_r1_pushed)
return;
r0->pmk_r1_pushed = 1;
@@ -1794,11 +4565,14 @@ void wpa_ft_push_pmk_r1(struct wpa_authenticator *wpa_auth, const u8 *addr)
wpa_printf(MSG_DEBUG, "FT: Deriving and pushing PMK-R1 keys to R1KHs "
"for STA " MACSTR, MAC2STR(addr));
- r1kh = wpa_auth->conf.r1kh_list;
- while (r1kh) {
- wpa_ft_generate_pmk_r1(wpa_auth, r0, r1kh, addr, r0->pairwise);
- r1kh = r1kh->next;
+ for (r1kh = *wpa_auth->conf.r1kh_list; r1kh; r1kh = r1kh->next) {
+ if (is_zero_ether_addr(r1kh->addr) ||
+ is_zero_ether_addr(r1kh->id))
+ continue;
+ if (wpa_ft_rrb_init_r1kh_seq(r1kh) < 0)
+ continue;
+ wpa_ft_generate_pmk_r1(wpa_auth, r0, r1kh, addr);
}
}
-#endif /* CONFIG_IEEE80211R */
+#endif /* CONFIG_IEEE80211R_AP */
diff --git a/freebsd/contrib/wpa/src/ap/wpa_auth_i.h b/freebsd/contrib/wpa/src/ap/wpa_auth_i.h
index 7fd8f05f..4babd0cb 100644
--- a/freebsd/contrib/wpa/src/ap/wpa_auth_i.h
+++ b/freebsd/contrib/wpa/src/ap/wpa_auth_i.h
@@ -9,24 +9,20 @@
#ifndef WPA_AUTH_I_H
#define WPA_AUTH_I_H
+#include "utils/list.h"
+
/* max(dot11RSNAConfigGroupUpdateCount,dot11RSNAConfigPairwiseUpdateCount) */
#define RSNA_MAX_EAPOL_RETRIES 4
struct wpa_group;
-struct wpa_stsl_negotiation {
- struct wpa_stsl_negotiation *next;
- u8 initiator[ETH_ALEN];
- u8 peer[ETH_ALEN];
-};
-
-
struct wpa_state_machine {
struct wpa_authenticator *wpa_auth;
struct wpa_group *group;
u8 addr[ETH_ALEN];
u8 p2p_dev_addr[ETH_ALEN];
+ u16 auth_alg;
enum {
WPA_PTK_INITIALIZE, WPA_PTK_DISCONNECT, WPA_PTK_DISCONNECTED,
@@ -48,8 +44,9 @@ struct wpa_state_machine {
Boolean AuthenticationRequest;
Boolean ReAuthenticationRequest;
Boolean Disconnect;
- int TimeoutCtr;
- int GTimeoutCtr;
+ u16 disconnect_reason; /* specific reason code to use with Disconnect */
+ u32 TimeoutCtr;
+ u32 GTimeoutCtr;
Boolean TimeoutEvt;
Boolean EAPOLKeyReceived;
Boolean EAPOLKeyPairwise;
@@ -62,6 +59,7 @@ struct wpa_state_machine {
u8 alt_replay_counter[WPA_REPLAY_COUNTER_LEN];
u8 PMK[PMK_LEN_MAX];
unsigned int pmk_len;
+ u8 pmkid[PMKID_LEN]; /* valid if pmkid_set == 1 */
struct wpa_ptk PTK;
Boolean PTK_valid;
Boolean pairwise_set;
@@ -89,11 +87,15 @@ struct wpa_state_machine {
unsigned int rx_eapol_key_secure:1;
unsigned int update_snonce:1;
unsigned int alt_snonce_valid:1;
-#ifdef CONFIG_IEEE80211R
+#ifdef CONFIG_IEEE80211R_AP
unsigned int ft_completed:1;
unsigned int pmk_r1_name_valid:1;
-#endif /* CONFIG_IEEE80211R */
+#endif /* CONFIG_IEEE80211R_AP */
unsigned int is_wnmsleep:1;
+ unsigned int pmkid_set:1;
+#ifdef CONFIG_OCV
+ unsigned int ocv_enabled:1;
+#endif /* CONFIG_OCV */
u8 req_replay_counter[WPA_REPLAY_COUNTER_LEN];
int req_replay_counter_used;
@@ -113,9 +115,12 @@ struct wpa_state_machine {
u32 dot11RSNAStatsTKIPLocalMICFailures;
u32 dot11RSNAStatsTKIPRemoteMICFailures;
-#ifdef CONFIG_IEEE80211R
- u8 xxkey[PMK_LEN]; /* PSK or the second 256 bits of MSK */
+#ifdef CONFIG_IEEE80211R_AP
+ u8 xxkey[PMK_LEN_MAX]; /* PSK or the second 256 bits of MSK, or the
+ * first 384 bits of MSK */
size_t xxkey_len;
+ u8 pmk_r1[PMK_LEN_MAX];
+ unsigned int pmk_r1_len;
u8 pmk_r1_name[WPA_PMK_NAME_LEN]; /* PMKR1Name derived from FT Auth
* Request */
u8 r0kh_id[FT_R0KH_ID_MAX_LEN]; /* R0KH-ID from FT Auth Request */
@@ -129,16 +134,34 @@ struct wpa_state_machine {
const u8 *ies, size_t ies_len);
void *ft_pending_cb_ctx;
struct wpabuf *ft_pending_req_ies;
- u8 ft_pending_pull_nonce[FT_R0KH_R1KH_PULL_NONCE_LEN];
+ u8 ft_pending_pull_nonce[FT_RRB_NONCE_LEN];
u8 ft_pending_auth_transaction;
u8 ft_pending_current_ap[ETH_ALEN];
-#endif /* CONFIG_IEEE80211R */
+ int ft_pending_pull_left_retries;
+#endif /* CONFIG_IEEE80211R_AP */
int pending_1_of_4_timeout;
#ifdef CONFIG_P2P
u8 ip_addr[4];
#endif /* CONFIG_P2P */
+
+#ifdef CONFIG_FILS
+ u8 fils_key_auth_sta[FILS_MAX_KEY_AUTH_LEN];
+ u8 fils_key_auth_ap[FILS_MAX_KEY_AUTH_LEN];
+ size_t fils_key_auth_len;
+ unsigned int fils_completed:1;
+#endif /* CONFIG_FILS */
+
+#ifdef CONFIG_DPP2
+ struct wpabuf *dpp_z;
+#endif /* CONFIG_DPP2 */
+
+#ifdef CONFIG_TESTING_OPTIONS
+ void (*eapol_status_cb)(void *ctx1, void *ctx2);
+ void *eapol_status_cb_ctx1;
+ void *eapol_status_cb_ctx2;
+#endif /* CONFIG_TESTING_OPTIONS */
};
@@ -194,10 +217,9 @@ struct wpa_authenticator {
unsigned int dot11RSNATKIPCounterMeasuresInvoked;
unsigned int dot11RSNA4WayHandshakeFailures;
- struct wpa_stsl_negotiation *stsl_negotiations;
-
struct wpa_auth_config conf;
- struct wpa_auth_callbacks cb;
+ const struct wpa_auth_callbacks *cb;
+ void *cb_ctx;
u8 *wpa_ie;
size_t wpa_ie_len;
@@ -213,6 +235,38 @@ struct wpa_authenticator {
};
+#ifdef CONFIG_IEEE80211R_AP
+
+#define FT_REMOTE_SEQ_BACKLOG 16
+struct ft_remote_seq_rx {
+ u32 dom;
+ struct os_reltime time_offset; /* local time - offset = remote time */
+
+ /* accepted sequence numbers: (offset ... offset + 0x40000000]
+ * (except those in last)
+ * dropped sequence numbers: (offset - 0x40000000 ... offset]
+ * all others trigger SEQ_REQ message (except first message)
+ */
+ u32 last[FT_REMOTE_SEQ_BACKLOG];
+ unsigned int num_last;
+ u32 offsetidx;
+
+ struct dl_list queue; /* send nonces + rrb msgs awaiting seq resp */
+};
+
+struct ft_remote_seq_tx {
+ u32 dom; /* non zero if initialized */
+ u32 seq;
+};
+
+struct ft_remote_seq {
+ struct ft_remote_seq_rx rx;
+ struct ft_remote_seq_tx tx;
+};
+
+#endif /* CONFIG_IEEE80211R_AP */
+
+
int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
const u8 *pmkid);
void wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr,
@@ -231,32 +285,19 @@ int wpa_auth_for_each_auth(struct wpa_authenticator *wpa_auth,
int (*cb)(struct wpa_authenticator *a, void *ctx),
void *cb_ctx);
-#ifdef CONFIG_PEERKEY
-int wpa_stsl_remove(struct wpa_authenticator *wpa_auth,
- struct wpa_stsl_negotiation *neg);
-void wpa_smk_error(struct wpa_authenticator *wpa_auth,
- struct wpa_state_machine *sm,
- const u8 *key_data, size_t key_data_len);
-void wpa_smk_m1(struct wpa_authenticator *wpa_auth,
- struct wpa_state_machine *sm, struct wpa_eapol_key *key,
- const u8 *key_data, size_t key_data_len);
-void wpa_smk_m3(struct wpa_authenticator *wpa_auth,
- struct wpa_state_machine *sm, struct wpa_eapol_key *key,
- const u8 *key_data, size_t key_data_len);
-#endif /* CONFIG_PEERKEY */
-
-#ifdef CONFIG_IEEE80211R
+#ifdef CONFIG_IEEE80211R_AP
int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len);
-int wpa_write_ftie(struct wpa_auth_config *conf, const u8 *r0kh_id,
- size_t r0kh_id_len,
+int wpa_write_ftie(struct wpa_auth_config *conf, int use_sha384,
+ const u8 *r0kh_id, size_t r0kh_id_len,
const u8 *anonce, const u8 *snonce,
u8 *buf, size_t len, const u8 *subelem,
size_t subelem_len);
-int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk,
- struct wpa_ptk *ptk);
+int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk);
struct wpa_ft_pmk_cache * wpa_ft_pmk_cache_init(void);
void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache);
void wpa_ft_install_ptk(struct wpa_state_machine *sm);
-#endif /* CONFIG_IEEE80211R */
+int wpa_ft_store_pmk_fils(struct wpa_state_machine *sm, const u8 *pmk_r0,
+ const u8 *pmk_r0_name);
+#endif /* CONFIG_IEEE80211R_AP */
#endif /* WPA_AUTH_I_H */
diff --git a/freebsd/contrib/wpa/src/ap/wpa_auth_ie.h b/freebsd/contrib/wpa/src/ap/wpa_auth_ie.h
index d2067ba3..a38b206f 100644
--- a/freebsd/contrib/wpa/src/ap/wpa_auth_ie.h
+++ b/freebsd/contrib/wpa/src/ap/wpa_auth_ie.h
@@ -19,30 +19,24 @@ struct wpa_eapol_ie_parse {
size_t gtk_len;
const u8 *mac_addr;
size_t mac_addr_len;
-#ifdef CONFIG_PEERKEY
- const u8 *smk;
- size_t smk_len;
- const u8 *nonce;
- size_t nonce_len;
- const u8 *lifetime;
- size_t lifetime_len;
- const u8 *error;
- size_t error_len;
-#endif /* CONFIG_PEERKEY */
#ifdef CONFIG_IEEE80211W
const u8 *igtk;
size_t igtk_len;
#endif /* CONFIG_IEEE80211W */
-#ifdef CONFIG_IEEE80211R
+#ifdef CONFIG_IEEE80211R_AP
const u8 *mdie;
size_t mdie_len;
const u8 *ftie;
size_t ftie_len;
-#endif /* CONFIG_IEEE80211R */
+#endif /* CONFIG_IEEE80211R_AP */
#ifdef CONFIG_P2P
const u8 *ip_addr_req;
const u8 *ip_addr_alloc;
#endif /* CONFIG_P2P */
+#ifdef CONFIG_OCV
+ const u8 *oci;
+ size_t oci_len;
+#endif /* CONFIG_OCV */
const u8 *osen;
size_t osen_len;
diff --git a/freebsd/contrib/wpa/src/common/ctrl_iface_common.c b/freebsd/contrib/wpa/src/common/ctrl_iface_common.c
index 72f539c4..265eda35 100644
--- a/freebsd/contrib/wpa/src/common/ctrl_iface_common.c
+++ b/freebsd/contrib/wpa/src/common/ctrl_iface_common.c
@@ -115,17 +115,53 @@ void sockaddr_print(int level, const char *msg, struct sockaddr_storage *sock,
}
+static int ctrl_set_events(struct wpa_ctrl_dst *dst, const char *input)
+{
+ const char *value;
+ int val;
+
+ if (!input)
+ return 0;
+
+ value = os_strchr(input, '=');
+ if (!value)
+ return -1;
+ value++;
+ val = atoi(value);
+ if (val < 0 || val > 1)
+ return -1;
+
+ if (str_starts(input, "probe_rx_events=")) {
+ if (val)
+ dst->events |= WPA_EVENT_RX_PROBE_REQUEST;
+ else
+ dst->events &= ~WPA_EVENT_RX_PROBE_REQUEST;
+ }
+
+ return 0;
+}
+
+
int ctrl_iface_attach(struct dl_list *ctrl_dst, struct sockaddr_storage *from,
- socklen_t fromlen)
+ socklen_t fromlen, const char *input)
{
struct wpa_ctrl_dst *dst;
+ /* Update event registration if already attached */
+ dl_list_for_each(dst, ctrl_dst, struct wpa_ctrl_dst, list) {
+ if (!sockaddr_compare(from, fromlen,
+ &dst->addr, dst->addrlen))
+ return ctrl_set_events(dst, input);
+ }
+
+ /* New attachment */
dst = os_zalloc(sizeof(*dst));
if (dst == NULL)
return -1;
os_memcpy(&dst->addr, from, fromlen);
dst->addrlen = fromlen;
dst->debug_level = MSG_INFO;
+ ctrl_set_events(dst, input);
dl_list_add(ctrl_dst, &dst->list);
sockaddr_print(MSG_DEBUG, "CTRL_IFACE monitor attached", from, fromlen);
diff --git a/freebsd/contrib/wpa/src/common/ctrl_iface_common.h b/freebsd/contrib/wpa/src/common/ctrl_iface_common.h
index 0b6e3e74..85e258e9 100644
--- a/freebsd/contrib/wpa/src/common/ctrl_iface_common.h
+++ b/freebsd/contrib/wpa/src/common/ctrl_iface_common.h
@@ -11,6 +11,9 @@
#include "utils/list.h"
+/* Events enable bits (wpa_ctrl_dst::events) */
+#define WPA_EVENT_RX_PROBE_REQUEST BIT(0)
+
/**
* struct wpa_ctrl_dst - Data structure of control interface monitors
*
@@ -23,13 +26,14 @@ struct wpa_ctrl_dst {
socklen_t addrlen;
int debug_level;
int errors;
+ u32 events; /* WPA_EVENT_* bitmap */
};
void sockaddr_print(int level, const char *msg, struct sockaddr_storage *sock,
socklen_t socklen);
int ctrl_iface_attach(struct dl_list *ctrl_dst, struct sockaddr_storage *from,
- socklen_t fromlen);
+ socklen_t fromlen, const char *input);
int ctrl_iface_detach(struct dl_list *ctrl_dst, struct sockaddr_storage *from,
socklen_t fromlen);
int ctrl_iface_level(struct dl_list *ctrl_dst, struct sockaddr_storage *from,
diff --git a/freebsd/contrib/wpa/src/common/defs.h b/freebsd/contrib/wpa/src/common/defs.h
index 4f567945..4faf1c86 100644
--- a/freebsd/contrib/wpa/src/common/defs.h
+++ b/freebsd/contrib/wpa/src/common/defs.h
@@ -1,6 +1,6 @@
/*
* WPA Supplicant - Common definitions
- * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -51,16 +51,35 @@ typedef enum { FALSE = 0, TRUE = 1 } Boolean;
#define WPA_KEY_MGMT_OSEN BIT(15)
#define WPA_KEY_MGMT_IEEE8021X_SUITE_B BIT(16)
#define WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 BIT(17)
+#define WPA_KEY_MGMT_FILS_SHA256 BIT(18)
+#define WPA_KEY_MGMT_FILS_SHA384 BIT(19)
+#define WPA_KEY_MGMT_FT_FILS_SHA256 BIT(20)
+#define WPA_KEY_MGMT_FT_FILS_SHA384 BIT(21)
+#define WPA_KEY_MGMT_OWE BIT(22)
+#define WPA_KEY_MGMT_DPP BIT(23)
+#define WPA_KEY_MGMT_FT_IEEE8021X_SHA384 BIT(24)
+
+#define WPA_KEY_MGMT_FT (WPA_KEY_MGMT_FT_PSK | \
+ WPA_KEY_MGMT_FT_IEEE8021X | \
+ WPA_KEY_MGMT_FT_IEEE8021X_SHA384 | \
+ WPA_KEY_MGMT_FT_SAE | \
+ WPA_KEY_MGMT_FT_FILS_SHA256 | \
+ WPA_KEY_MGMT_FT_FILS_SHA384)
static inline int wpa_key_mgmt_wpa_ieee8021x(int akm)
{
return !!(akm & (WPA_KEY_MGMT_IEEE8021X |
WPA_KEY_MGMT_FT_IEEE8021X |
+ WPA_KEY_MGMT_FT_IEEE8021X_SHA384 |
WPA_KEY_MGMT_CCKM |
WPA_KEY_MGMT_OSEN |
WPA_KEY_MGMT_IEEE8021X_SHA256 |
WPA_KEY_MGMT_IEEE8021X_SUITE_B |
- WPA_KEY_MGMT_IEEE8021X_SUITE_B_192));
+ WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 |
+ WPA_KEY_MGMT_FILS_SHA256 |
+ WPA_KEY_MGMT_FILS_SHA384 |
+ WPA_KEY_MGMT_FT_FILS_SHA256 |
+ WPA_KEY_MGMT_FT_FILS_SHA384));
}
static inline int wpa_key_mgmt_wpa_psk(int akm)
@@ -74,9 +93,19 @@ static inline int wpa_key_mgmt_wpa_psk(int akm)
static inline int wpa_key_mgmt_ft(int akm)
{
- return !!(akm & (WPA_KEY_MGMT_FT_PSK |
- WPA_KEY_MGMT_FT_IEEE8021X |
- WPA_KEY_MGMT_FT_SAE));
+ return !!(akm & WPA_KEY_MGMT_FT);
+}
+
+static inline int wpa_key_mgmt_only_ft(int akm)
+{
+ int ft = wpa_key_mgmt_ft(akm);
+ akm &= ~WPA_KEY_MGMT_FT;
+ return ft && !akm;
+}
+
+static inline int wpa_key_mgmt_ft_psk(int akm)
+{
+ return !!(akm & WPA_KEY_MGMT_FT_PSK);
}
static inline int wpa_key_mgmt_sae(int akm)
@@ -85,17 +114,32 @@ static inline int wpa_key_mgmt_sae(int akm)
WPA_KEY_MGMT_FT_SAE));
}
+static inline int wpa_key_mgmt_fils(int akm)
+{
+ return !!(akm & (WPA_KEY_MGMT_FILS_SHA256 |
+ WPA_KEY_MGMT_FILS_SHA384 |
+ WPA_KEY_MGMT_FT_FILS_SHA256 |
+ WPA_KEY_MGMT_FT_FILS_SHA384));
+}
+
static inline int wpa_key_mgmt_sha256(int akm)
{
return !!(akm & (WPA_KEY_MGMT_PSK_SHA256 |
WPA_KEY_MGMT_IEEE8021X_SHA256 |
+ WPA_KEY_MGMT_SAE |
+ WPA_KEY_MGMT_FT_SAE |
WPA_KEY_MGMT_OSEN |
- WPA_KEY_MGMT_IEEE8021X_SUITE_B));
+ WPA_KEY_MGMT_IEEE8021X_SUITE_B |
+ WPA_KEY_MGMT_FILS_SHA256 |
+ WPA_KEY_MGMT_FT_FILS_SHA256));
}
static inline int wpa_key_mgmt_sha384(int akm)
{
- return !!(akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192);
+ return !!(akm & (WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 |
+ WPA_KEY_MGMT_FT_IEEE8021X_SHA384 |
+ WPA_KEY_MGMT_FILS_SHA384 |
+ WPA_KEY_MGMT_FT_FILS_SHA384));
}
static inline int wpa_key_mgmt_suite_b(int akm)
@@ -108,7 +152,10 @@ static inline int wpa_key_mgmt_wpa(int akm)
{
return wpa_key_mgmt_wpa_ieee8021x(akm) ||
wpa_key_mgmt_wpa_psk(akm) ||
- wpa_key_mgmt_sae(akm);
+ wpa_key_mgmt_fils(akm) ||
+ wpa_key_mgmt_sae(akm) ||
+ akm == WPA_KEY_MGMT_OWE ||
+ akm == WPA_KEY_MGMT_DPP;
}
static inline int wpa_key_mgmt_wpa_any(int akm)
@@ -132,7 +179,13 @@ static inline int wpa_key_mgmt_cckm(int akm)
#define WPA_AUTH_ALG_LEAP BIT(2)
#define WPA_AUTH_ALG_FT BIT(3)
#define WPA_AUTH_ALG_SAE BIT(4)
+#define WPA_AUTH_ALG_FILS BIT(5)
+#define WPA_AUTH_ALG_FILS_SK_PFS BIT(6)
+static inline int wpa_auth_alg_fils(int alg)
+{
+ return !!(alg & (WPA_AUTH_ALG_FILS | WPA_AUTH_ALG_FILS_SK_PFS));
+}
enum wpa_alg {
WPA_ALG_NONE,
@@ -341,4 +394,29 @@ enum wpa_radio_work_band {
BAND_60_GHZ = BIT(2),
};
+enum beacon_rate_type {
+ BEACON_RATE_LEGACY,
+ BEACON_RATE_HT,
+ BEACON_RATE_VHT
+};
+
+enum eap_proxy_sim_state {
+ SIM_STATE_ERROR,
+};
+
+#define OCE_STA BIT(0)
+#define OCE_STA_CFON BIT(1)
+#define OCE_AP BIT(2)
+
+/* enum chan_width - Channel width definitions */
+enum chan_width {
+ CHAN_WIDTH_20_NOHT,
+ CHAN_WIDTH_20,
+ CHAN_WIDTH_40,
+ CHAN_WIDTH_80,
+ CHAN_WIDTH_80P80,
+ CHAN_WIDTH_160,
+ CHAN_WIDTH_UNKNOWN
+};
+
#endif /* DEFS_H */
diff --git a/freebsd/contrib/wpa/src/common/dpp.h b/freebsd/contrib/wpa/src/common/dpp.h
new file mode 100644
index 00000000..5a6d8cc7
--- /dev/null
+++ b/freebsd/contrib/wpa/src/common/dpp.h
@@ -0,0 +1,505 @@
+/*
+ * DPP functionality shared between hostapd and wpa_supplicant
+ * Copyright (c) 2017, Qualcomm Atheros, Inc.
+ * Copyright (c) 2018-2019, The Linux Foundation
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef DPP_H
+#define DPP_H
+
+#ifdef CONFIG_DPP
+#include <openssl/x509.h>
+
+#include "utils/list.h"
+#include "common/wpa_common.h"
+#include "crypto/sha256.h"
+
+struct crypto_ecdh;
+struct dpp_global;
+
+#define DPP_HDR_LEN (4 + 2) /* OUI, OUI Type, Crypto Suite, DPP frame type */
+
+enum dpp_public_action_frame_type {
+ DPP_PA_AUTHENTICATION_REQ = 0,
+ DPP_PA_AUTHENTICATION_RESP = 1,
+ DPP_PA_AUTHENTICATION_CONF = 2,
+ DPP_PA_PEER_DISCOVERY_REQ = 5,
+ DPP_PA_PEER_DISCOVERY_RESP = 6,
+ DPP_PA_PKEX_EXCHANGE_REQ = 7,
+ DPP_PA_PKEX_EXCHANGE_RESP = 8,
+ DPP_PA_PKEX_COMMIT_REVEAL_REQ = 9,
+ DPP_PA_PKEX_COMMIT_REVEAL_RESP = 10,
+ DPP_PA_CONFIGURATION_RESULT = 11,
+};
+
+enum dpp_attribute_id {
+ DPP_ATTR_STATUS = 0x1000,
+ DPP_ATTR_I_BOOTSTRAP_KEY_HASH = 0x1001,
+ DPP_ATTR_R_BOOTSTRAP_KEY_HASH = 0x1002,
+ DPP_ATTR_I_PROTOCOL_KEY = 0x1003,
+ DPP_ATTR_WRAPPED_DATA = 0x1004,
+ DPP_ATTR_I_NONCE = 0x1005,
+ DPP_ATTR_I_CAPABILITIES = 0x1006,
+ DPP_ATTR_R_NONCE = 0x1007,
+ DPP_ATTR_R_CAPABILITIES = 0x1008,
+ DPP_ATTR_R_PROTOCOL_KEY = 0x1009,
+ DPP_ATTR_I_AUTH_TAG = 0x100A,
+ DPP_ATTR_R_AUTH_TAG = 0x100B,
+ DPP_ATTR_CONFIG_OBJ = 0x100C,
+ DPP_ATTR_CONNECTOR = 0x100D,
+ DPP_ATTR_CONFIG_ATTR_OBJ = 0x100E,
+ DPP_ATTR_BOOTSTRAP_KEY = 0x100F,
+ DPP_ATTR_OWN_NET_NK_HASH = 0x1011,
+ DPP_ATTR_FINITE_CYCLIC_GROUP = 0x1012,
+ DPP_ATTR_ENCRYPTED_KEY = 0x1013,
+ DPP_ATTR_ENROLLEE_NONCE = 0x1014,
+ DPP_ATTR_CODE_IDENTIFIER = 0x1015,
+ DPP_ATTR_TRANSACTION_ID = 0x1016,
+ DPP_ATTR_BOOTSTRAP_INFO = 0x1017,
+ DPP_ATTR_CHANNEL = 0x1018,
+ DPP_ATTR_PROTOCOL_VERSION = 0x1019,
+ DPP_ATTR_ENVELOPED_DATA = 0x101A,
+};
+
+enum dpp_status_error {
+ DPP_STATUS_OK = 0,
+ DPP_STATUS_NOT_COMPATIBLE = 1,
+ DPP_STATUS_AUTH_FAILURE = 2,
+ DPP_STATUS_UNWRAP_FAILURE = 3,
+ DPP_STATUS_BAD_GROUP = 4,
+ DPP_STATUS_CONFIGURE_FAILURE = 5,
+ DPP_STATUS_RESPONSE_PENDING = 6,
+ DPP_STATUS_INVALID_CONNECTOR = 7,
+ DPP_STATUS_NO_MATCH = 8,
+ DPP_STATUS_CONFIG_REJECTED = 9,
+};
+
+#define DPP_CAPAB_ENROLLEE BIT(0)
+#define DPP_CAPAB_CONFIGURATOR BIT(1)
+#define DPP_CAPAB_ROLE_MASK (BIT(0) | BIT(1))
+
+#define DPP_BOOTSTRAP_MAX_FREQ 30
+#define DPP_MAX_NONCE_LEN 32
+#define DPP_MAX_HASH_LEN 64
+#define DPP_MAX_SHARED_SECRET_LEN 66
+
+struct dpp_curve_params {
+ const char *name;
+ size_t hash_len;
+ size_t aes_siv_key_len;
+ size_t nonce_len;
+ size_t prime_len;
+ const char *jwk_crv;
+ u16 ike_group;
+ const char *jws_alg;
+};
+
+enum dpp_bootstrap_type {
+ DPP_BOOTSTRAP_QR_CODE,
+ DPP_BOOTSTRAP_PKEX,
+};
+
+struct dpp_bootstrap_info {
+ struct dl_list list;
+ unsigned int id;
+ enum dpp_bootstrap_type type;
+ char *uri;
+ u8 mac_addr[ETH_ALEN];
+ char *info;
+ unsigned int freq[DPP_BOOTSTRAP_MAX_FREQ];
+ unsigned int num_freq;
+ int own;
+ EVP_PKEY *pubkey;
+ u8 pubkey_hash[SHA256_MAC_LEN];
+ const struct dpp_curve_params *curve;
+ unsigned int pkex_t; /* number of failures before dpp_pkex
+ * instantiation */
+};
+
+#define PKEX_COUNTER_T_LIMIT 5
+
+struct dpp_pkex {
+ void *msg_ctx;
+ unsigned int initiator:1;
+ unsigned int exchange_done:1;
+ unsigned int failed:1;
+ struct dpp_bootstrap_info *own_bi;
+ u8 own_mac[ETH_ALEN];
+ u8 peer_mac[ETH_ALEN];
+ char *identifier;
+ char *code;
+ EVP_PKEY *x;
+ EVP_PKEY *y;
+ u8 Mx[DPP_MAX_SHARED_SECRET_LEN];
+ u8 Nx[DPP_MAX_SHARED_SECRET_LEN];
+ u8 z[DPP_MAX_HASH_LEN];
+ EVP_PKEY *peer_bootstrap_key;
+ struct wpabuf *exchange_req;
+ struct wpabuf *exchange_resp;
+ unsigned int t; /* number of failures on code use */
+ unsigned int exch_req_wait_time;
+ unsigned int exch_req_tries;
+ unsigned int freq;
+};
+
+enum dpp_akm {
+ DPP_AKM_UNKNOWN,
+ DPP_AKM_DPP,
+ DPP_AKM_PSK,
+ DPP_AKM_SAE,
+ DPP_AKM_PSK_SAE,
+ DPP_AKM_SAE_DPP,
+ DPP_AKM_PSK_SAE_DPP,
+};
+
+struct dpp_configuration {
+ u8 ssid[32];
+ size_t ssid_len;
+ enum dpp_akm akm;
+
+ /* For DPP configuration (connector) */
+ os_time_t netaccesskey_expiry;
+
+ /* TODO: groups */
+ char *group_id;
+
+ /* For legacy configuration */
+ char *passphrase;
+ u8 psk[32];
+ int psk_set;
+};
+
+struct dpp_authentication {
+ void *msg_ctx;
+ u8 peer_version;
+ const struct dpp_curve_params *curve;
+ struct dpp_bootstrap_info *peer_bi;
+ struct dpp_bootstrap_info *own_bi;
+ struct dpp_bootstrap_info *tmp_own_bi;
+ u8 waiting_pubkey_hash[SHA256_MAC_LEN];
+ int response_pending;
+ enum dpp_status_error auth_resp_status;
+ enum dpp_status_error conf_resp_status;
+ u8 peer_mac_addr[ETH_ALEN];
+ u8 i_nonce[DPP_MAX_NONCE_LEN];
+ u8 r_nonce[DPP_MAX_NONCE_LEN];
+ u8 e_nonce[DPP_MAX_NONCE_LEN];
+ u8 i_capab;
+ u8 r_capab;
+ EVP_PKEY *own_protocol_key;
+ EVP_PKEY *peer_protocol_key;
+ struct wpabuf *req_msg;
+ struct wpabuf *resp_msg;
+ /* Intersection of possible frequencies for initiating DPP
+ * Authentication exchange */
+ unsigned int freq[DPP_BOOTSTRAP_MAX_FREQ];
+ unsigned int num_freq, freq_idx;
+ unsigned int curr_freq;
+ unsigned int neg_freq;
+ unsigned int num_freq_iters;
+ size_t secret_len;
+ u8 Mx[DPP_MAX_SHARED_SECRET_LEN];
+ size_t Mx_len;
+ u8 Nx[DPP_MAX_SHARED_SECRET_LEN];
+ size_t Nx_len;
+ u8 Lx[DPP_MAX_SHARED_SECRET_LEN];
+ size_t Lx_len;
+ u8 k1[DPP_MAX_HASH_LEN];
+ u8 k2[DPP_MAX_HASH_LEN];
+ u8 ke[DPP_MAX_HASH_LEN];
+ int initiator;
+ int waiting_auth_resp;
+ int waiting_auth_conf;
+ int auth_req_ack;
+ unsigned int auth_resp_tries;
+ u8 allowed_roles;
+ int configurator;
+ int remove_on_tx_status;
+ int connect_on_tx_status;
+ int waiting_conf_result;
+ int auth_success;
+ struct wpabuf *conf_req;
+ const struct wpabuf *conf_resp; /* owned by GAS server */
+ struct dpp_configuration *conf_ap;
+ struct dpp_configuration *conf_sta;
+ struct dpp_configurator *conf;
+ char *connector; /* received signedConnector */
+ u8 ssid[SSID_MAX_LEN];
+ u8 ssid_len;
+ char passphrase[64];
+ u8 psk[PMK_LEN];
+ int psk_set;
+ enum dpp_akm akm;
+ struct wpabuf *net_access_key;
+ os_time_t net_access_key_expiry;
+ struct wpabuf *c_sign_key;
+#ifdef CONFIG_TESTING_OPTIONS
+ char *config_obj_override;
+ char *discovery_override;
+ char *groups_override;
+ unsigned int ignore_netaccesskey_mismatch:1;
+#endif /* CONFIG_TESTING_OPTIONS */
+};
+
+struct dpp_configurator {
+ struct dl_list list;
+ unsigned int id;
+ int own;
+ EVP_PKEY *csign;
+ char *kid;
+ const struct dpp_curve_params *curve;
+};
+
+struct dpp_introduction {
+ u8 pmkid[PMKID_LEN];
+ u8 pmk[PMK_LEN_MAX];
+ size_t pmk_len;
+};
+
+#ifdef CONFIG_TESTING_OPTIONS
+enum dpp_test_behavior {
+ DPP_TEST_DISABLED = 0,
+ DPP_TEST_AFTER_WRAPPED_DATA_AUTH_REQ = 1,
+ DPP_TEST_AFTER_WRAPPED_DATA_AUTH_RESP = 2,
+ DPP_TEST_AFTER_WRAPPED_DATA_AUTH_CONF = 3,
+ DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_REQ = 4,
+ DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_RESP = 5,
+ DPP_TEST_AFTER_WRAPPED_DATA_CONF_REQ = 6,
+ DPP_TEST_AFTER_WRAPPED_DATA_CONF_RESP = 7,
+ DPP_TEST_ZERO_I_CAPAB = 8,
+ DPP_TEST_ZERO_R_CAPAB = 9,
+ DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_REQ = 10,
+ DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_REQ = 11,
+ DPP_TEST_NO_I_PROTO_KEY_AUTH_REQ = 12,
+ DPP_TEST_NO_I_NONCE_AUTH_REQ = 13,
+ DPP_TEST_NO_I_CAPAB_AUTH_REQ = 14,
+ DPP_TEST_NO_WRAPPED_DATA_AUTH_REQ = 15,
+ DPP_TEST_NO_STATUS_AUTH_RESP = 16,
+ DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_RESP = 17,
+ DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_RESP = 18,
+ DPP_TEST_NO_R_PROTO_KEY_AUTH_RESP = 19,
+ DPP_TEST_NO_R_NONCE_AUTH_RESP = 20,
+ DPP_TEST_NO_I_NONCE_AUTH_RESP = 21,
+ DPP_TEST_NO_R_CAPAB_AUTH_RESP = 22,
+ DPP_TEST_NO_R_AUTH_AUTH_RESP = 23,
+ DPP_TEST_NO_WRAPPED_DATA_AUTH_RESP = 24,
+ DPP_TEST_NO_STATUS_AUTH_CONF = 25,
+ DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_CONF = 26,
+ DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_CONF = 27,
+ DPP_TEST_NO_I_AUTH_AUTH_CONF = 28,
+ DPP_TEST_NO_WRAPPED_DATA_AUTH_CONF = 29,
+ DPP_TEST_I_NONCE_MISMATCH_AUTH_RESP = 30,
+ DPP_TEST_INCOMPATIBLE_R_CAPAB_AUTH_RESP = 31,
+ DPP_TEST_R_AUTH_MISMATCH_AUTH_RESP = 32,
+ DPP_TEST_I_AUTH_MISMATCH_AUTH_CONF = 33,
+ DPP_TEST_NO_FINITE_CYCLIC_GROUP_PKEX_EXCHANGE_REQ = 34,
+ DPP_TEST_NO_ENCRYPTED_KEY_PKEX_EXCHANGE_REQ = 35,
+ DPP_TEST_NO_STATUS_PKEX_EXCHANGE_RESP = 36,
+ DPP_TEST_NO_ENCRYPTED_KEY_PKEX_EXCHANGE_RESP = 37,
+ DPP_TEST_NO_BOOTSTRAP_KEY_PKEX_CR_REQ = 38,
+ DPP_TEST_NO_I_AUTH_TAG_PKEX_CR_REQ = 39,
+ DPP_TEST_NO_WRAPPED_DATA_PKEX_CR_REQ = 40,
+ DPP_TEST_NO_BOOTSTRAP_KEY_PKEX_CR_RESP = 41,
+ DPP_TEST_NO_R_AUTH_TAG_PKEX_CR_RESP = 42,
+ DPP_TEST_NO_WRAPPED_DATA_PKEX_CR_RESP = 43,
+ DPP_TEST_INVALID_ENCRYPTED_KEY_PKEX_EXCHANGE_REQ = 44,
+ DPP_TEST_INVALID_ENCRYPTED_KEY_PKEX_EXCHANGE_RESP = 45,
+ DPP_TEST_INVALID_STATUS_PKEX_EXCHANGE_RESP = 46,
+ DPP_TEST_INVALID_BOOTSTRAP_KEY_PKEX_CR_REQ = 47,
+ DPP_TEST_INVALID_BOOTSTRAP_KEY_PKEX_CR_RESP = 48,
+ DPP_TEST_I_AUTH_TAG_MISMATCH_PKEX_CR_REQ = 49,
+ DPP_TEST_R_AUTH_TAG_MISMATCH_PKEX_CR_RESP = 50,
+ DPP_TEST_NO_E_NONCE_CONF_REQ = 51,
+ DPP_TEST_NO_CONFIG_ATTR_OBJ_CONF_REQ = 52,
+ DPP_TEST_NO_WRAPPED_DATA_CONF_REQ = 53,
+ DPP_TEST_NO_E_NONCE_CONF_RESP = 54,
+ DPP_TEST_NO_CONFIG_OBJ_CONF_RESP = 55,
+ DPP_TEST_NO_STATUS_CONF_RESP = 56,
+ DPP_TEST_NO_WRAPPED_DATA_CONF_RESP = 57,
+ DPP_TEST_INVALID_STATUS_CONF_RESP = 58,
+ DPP_TEST_E_NONCE_MISMATCH_CONF_RESP = 59,
+ DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_REQ = 60,
+ DPP_TEST_NO_CONNECTOR_PEER_DISC_REQ = 61,
+ DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_RESP = 62,
+ DPP_TEST_NO_STATUS_PEER_DISC_RESP = 63,
+ DPP_TEST_NO_CONNECTOR_PEER_DISC_RESP = 64,
+ DPP_TEST_AUTH_RESP_IN_PLACE_OF_CONF = 65,
+ DPP_TEST_INVALID_I_PROTO_KEY_AUTH_REQ = 66,
+ DPP_TEST_INVALID_R_PROTO_KEY_AUTH_RESP = 67,
+ DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_REQ = 68,
+ DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_REQ = 69,
+ DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_RESP = 70,
+ DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_RESP = 71,
+ DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_CONF = 72,
+ DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_CONF = 73,
+ DPP_TEST_INVALID_STATUS_AUTH_RESP = 74,
+ DPP_TEST_INVALID_STATUS_AUTH_CONF = 75,
+ DPP_TEST_INVALID_CONFIG_ATTR_OBJ_CONF_REQ = 76,
+ DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_RESP = 77,
+ DPP_TEST_INVALID_STATUS_PEER_DISC_RESP = 78,
+ DPP_TEST_INVALID_CONNECTOR_PEER_DISC_RESP = 79,
+ DPP_TEST_INVALID_CONNECTOR_PEER_DISC_REQ = 80,
+ DPP_TEST_INVALID_I_NONCE_AUTH_REQ = 81,
+ DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_REQ = 82,
+ DPP_TEST_INVALID_E_NONCE_CONF_REQ = 83,
+ DPP_TEST_STOP_AT_PKEX_EXCHANGE_RESP = 84,
+ DPP_TEST_STOP_AT_PKEX_CR_REQ = 85,
+ DPP_TEST_STOP_AT_PKEX_CR_RESP = 86,
+ DPP_TEST_STOP_AT_AUTH_REQ = 87,
+ DPP_TEST_STOP_AT_AUTH_RESP = 88,
+ DPP_TEST_STOP_AT_AUTH_CONF = 89,
+ DPP_TEST_STOP_AT_CONF_REQ = 90,
+ DPP_TEST_REJECT_CONFIG = 91,
+};
+
+extern enum dpp_test_behavior dpp_test;
+extern u8 dpp_pkex_own_mac_override[ETH_ALEN];
+extern u8 dpp_pkex_peer_mac_override[ETH_ALEN];
+extern u8 dpp_pkex_ephemeral_key_override[600];
+extern size_t dpp_pkex_ephemeral_key_override_len;
+extern u8 dpp_protocol_key_override[600];
+extern size_t dpp_protocol_key_override_len;
+extern u8 dpp_nonce_override[DPP_MAX_NONCE_LEN];
+extern size_t dpp_nonce_override_len;
+#endif /* CONFIG_TESTING_OPTIONS */
+
+void dpp_bootstrap_info_free(struct dpp_bootstrap_info *info);
+const char * dpp_bootstrap_type_txt(enum dpp_bootstrap_type type);
+int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi);
+int dpp_parse_uri_chan_list(struct dpp_bootstrap_info *bi,
+ const char *chan_list);
+int dpp_parse_uri_mac(struct dpp_bootstrap_info *bi, const char *mac);
+int dpp_parse_uri_info(struct dpp_bootstrap_info *bi, const char *info);
+struct dpp_bootstrap_info * dpp_parse_qr_code(const char *uri);
+char * dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve,
+ const u8 *privkey, size_t privkey_len);
+struct hostapd_hw_modes;
+struct dpp_authentication * dpp_auth_init(void *msg_ctx,
+ struct dpp_bootstrap_info *peer_bi,
+ struct dpp_bootstrap_info *own_bi,
+ u8 dpp_allowed_roles,
+ unsigned int neg_freq,
+ struct hostapd_hw_modes *own_modes,
+ u16 num_modes);
+struct dpp_authentication *
+dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual,
+ struct dpp_bootstrap_info *peer_bi,
+ struct dpp_bootstrap_info *own_bi,
+ unsigned int freq, const u8 *hdr, const u8 *attr_start,
+ size_t attr_len);
+struct wpabuf *
+dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr,
+ const u8 *attr_start, size_t attr_len);
+struct wpabuf * dpp_build_conf_req(struct dpp_authentication *auth,
+ const char *json);
+int dpp_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr,
+ const u8 *attr_start, size_t attr_len);
+int dpp_notify_new_qr_code(struct dpp_authentication *auth,
+ struct dpp_bootstrap_info *peer_bi);
+struct dpp_configuration * dpp_configuration_alloc(const char *type);
+int dpp_akm_psk(enum dpp_akm akm);
+int dpp_akm_sae(enum dpp_akm akm);
+int dpp_akm_legacy(enum dpp_akm akm);
+int dpp_akm_dpp(enum dpp_akm akm);
+int dpp_akm_ver2(enum dpp_akm akm);
+int dpp_configuration_valid(const struct dpp_configuration *conf);
+void dpp_configuration_free(struct dpp_configuration *conf);
+int dpp_set_configurator(struct dpp_global *dpp, void *msg_ctx,
+ struct dpp_authentication *auth,
+ const char *cmd);
+void dpp_auth_deinit(struct dpp_authentication *auth);
+struct wpabuf *
+dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start,
+ size_t attr_len);
+int dpp_conf_resp_rx(struct dpp_authentication *auth,
+ const struct wpabuf *resp);
+enum dpp_status_error dpp_conf_result_rx(struct dpp_authentication *auth,
+ const u8 *hdr,
+ const u8 *attr_start, size_t attr_len);
+struct wpabuf * dpp_build_conf_result(struct dpp_authentication *auth,
+ enum dpp_status_error status);
+struct wpabuf * dpp_alloc_msg(enum dpp_public_action_frame_type type,
+ size_t len);
+const u8 * dpp_get_attr(const u8 *buf, size_t len, u16 req_id, u16 *ret_len);
+int dpp_check_attrs(const u8 *buf, size_t len);
+int dpp_key_expired(const char *timestamp, os_time_t *expiry);
+const char * dpp_akm_str(enum dpp_akm akm);
+int dpp_configurator_get_key(const struct dpp_configurator *conf, char *buf,
+ size_t buflen);
+void dpp_configurator_free(struct dpp_configurator *conf);
+struct dpp_configurator *
+dpp_keygen_configurator(const char *curve, const u8 *privkey,
+ size_t privkey_len);
+int dpp_configurator_own_config(struct dpp_authentication *auth,
+ const char *curve, int ap);
+enum dpp_status_error
+dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
+ const u8 *net_access_key, size_t net_access_key_len,
+ const u8 *csign_key, size_t csign_key_len,
+ const u8 *peer_connector, size_t peer_connector_len,
+ os_time_t *expiry);
+struct dpp_pkex * dpp_pkex_init(void *msg_ctx, struct dpp_bootstrap_info *bi,
+ const u8 *own_mac,
+ const char *identifier,
+ const char *code);
+struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
+ struct dpp_bootstrap_info *bi,
+ const u8 *own_mac,
+ const u8 *peer_mac,
+ const char *identifier,
+ const char *code,
+ const u8 *buf, size_t len);
+struct wpabuf * dpp_pkex_rx_exchange_resp(struct dpp_pkex *pkex,
+ const u8 *peer_mac,
+ const u8 *buf, size_t len);
+struct wpabuf * dpp_pkex_rx_commit_reveal_req(struct dpp_pkex *pkex,
+ const u8 *hdr,
+ const u8 *buf, size_t len);
+int dpp_pkex_rx_commit_reveal_resp(struct dpp_pkex *pkex, const u8 *hdr,
+ const u8 *buf, size_t len);
+void dpp_pkex_free(struct dpp_pkex *pkex);
+
+char * dpp_corrupt_connector_signature(const char *connector);
+
+
+struct dpp_pfs {
+ struct crypto_ecdh *ecdh;
+ const struct dpp_curve_params *curve;
+ struct wpabuf *ie;
+ struct wpabuf *secret;
+};
+
+struct dpp_pfs * dpp_pfs_init(const u8 *net_access_key,
+ size_t net_access_key_len);
+int dpp_pfs_process(struct dpp_pfs *pfs, const u8 *peer_ie, size_t peer_ie_len);
+void dpp_pfs_free(struct dpp_pfs *pfs);
+
+struct dpp_bootstrap_info * dpp_add_qr_code(struct dpp_global *dpp,
+ const char *uri);
+int dpp_bootstrap_gen(struct dpp_global *dpp, const char *cmd);
+struct dpp_bootstrap_info *
+dpp_bootstrap_get_id(struct dpp_global *dpp, unsigned int id);
+int dpp_bootstrap_remove(struct dpp_global *dpp, const char *id);
+struct dpp_bootstrap_info *
+dpp_pkex_finish(struct dpp_global *dpp, struct dpp_pkex *pkex, const u8 *peer,
+ unsigned int freq);
+const char * dpp_bootstrap_get_uri(struct dpp_global *dpp, unsigned int id);
+int dpp_bootstrap_info(struct dpp_global *dpp, int id,
+ char *reply, int reply_size);
+void dpp_bootstrap_find_pair(struct dpp_global *dpp, const u8 *i_bootstrap,
+ const u8 *r_bootstrap,
+ struct dpp_bootstrap_info **own_bi,
+ struct dpp_bootstrap_info **peer_bi);
+int dpp_configurator_add(struct dpp_global *dpp, const char *cmd);
+int dpp_configurator_remove(struct dpp_global *dpp, const char *id);
+int dpp_configurator_get_key_id(struct dpp_global *dpp, unsigned int id,
+ char *buf, size_t buflen);
+struct dpp_global * dpp_global_init(void);
+void dpp_global_clear(struct dpp_global *dpp);
+void dpp_global_deinit(struct dpp_global *dpp);
+
+#endif /* CONFIG_DPP */
+#endif /* DPP_H */
diff --git a/freebsd/contrib/wpa/src/common/gas.c b/freebsd/contrib/wpa/src/common/gas.c
index 1aa3c806..bddc37a6 100644
--- a/freebsd/contrib/wpa/src/common/gas.c
+++ b/freebsd/contrib/wpa/src/common/gas.c
@@ -77,7 +77,7 @@ gas_build_initial_resp(u8 dialog_token, u16 status_code, u16 comeback_delay,
}
-static struct wpabuf *
+struct wpabuf *
gas_build_comeback_resp(u8 dialog_token, u16 status_code, u8 frag_id, u8 more,
u16 comeback_delay, size_t size)
{
diff --git a/freebsd/contrib/wpa/src/common/gas.h b/freebsd/contrib/wpa/src/common/gas.h
index 306adc58..4c93e311 100644
--- a/freebsd/contrib/wpa/src/common/gas.h
+++ b/freebsd/contrib/wpa/src/common/gas.h
@@ -14,6 +14,9 @@ struct wpabuf * gas_build_initial_req(u8 dialog_token, size_t size);
struct wpabuf * gas_build_comeback_req(u8 dialog_token);
struct wpabuf * gas_build_initial_resp(u8 dialog_token, u16 status_code,
u16 comeback_delay, size_t size);
+struct wpabuf *
+gas_build_comeback_resp(u8 dialog_token, u16 status_code, u8 frag_id, u8 more,
+ u16 comeback_delay, size_t size);
struct wpabuf * gas_anqp_build_initial_req(u8 dialog_token, size_t size);
struct wpabuf * gas_anqp_build_initial_resp(u8 dialog_token, u16 status_code,
u16 comeback_delay, size_t size);
diff --git a/freebsd/contrib/wpa/src/common/gas_server.h b/freebsd/contrib/wpa/src/common/gas_server.h
new file mode 100644
index 00000000..299f529f
--- /dev/null
+++ b/freebsd/contrib/wpa/src/common/gas_server.h
@@ -0,0 +1,44 @@
+/*
+ * Generic advertisement service (GAS) server
+ * Copyright (c) 2017, Qualcomm Atheros, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef GAS_SERVER_H
+#define GAS_SERVER_H
+
+#ifdef CONFIG_GAS_SERVER
+
+struct gas_server;
+
+struct gas_server * gas_server_init(void *ctx,
+ void (*tx)(void *ctx, int freq,
+ const u8 *da,
+ struct wpabuf *buf,
+ unsigned int wait_time));
+void gas_server_deinit(struct gas_server *gas);
+int gas_server_register(struct gas_server *gas,
+ const u8 *adv_proto_id, u8 adv_proto_id_len,
+ struct wpabuf *
+ (*req_cb)(void *ctx, const u8 *sa,
+ const u8 *query, size_t query_len),
+ void (*status_cb)(void *ctx, struct wpabuf *resp,
+ int ok),
+ void *ctx);
+int gas_server_rx(struct gas_server *gas, const u8 *da, const u8 *sa,
+ const u8 *bssid, u8 categ, const u8 *data, size_t len,
+ int freq);
+void gas_server_tx_status(struct gas_server *gas, const u8 *dst, const u8 *data,
+ size_t data_len, int ack);
+
+#else /* CONFIG_GAS_SERVER */
+
+static inline void gas_server_deinit(struct gas_server *gas)
+{
+}
+
+#endif /* CONFIG_GAS_SERVER */
+
+#endif /* GAS_SERVER_H */
diff --git a/freebsd/contrib/wpa/src/common/hw_features_common.c b/freebsd/contrib/wpa/src/common/hw_features_common.c
index 81b8e695..33d0d879 100644
--- a/freebsd/contrib/wpa/src/common/hw_features_common.c
+++ b/freebsd/contrib/wpa/src/common/hw_features_common.c
@@ -89,13 +89,29 @@ int hw_get_chan(struct hostapd_hw_modes *mode, int freq)
int allowed_ht40_channel_pair(struct hostapd_hw_modes *mode, int pri_chan,
int sec_chan)
{
- int ok, j, first;
+ int ok, first;
int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 140,
- 149, 157, 184, 192 };
+ 149, 157, 165, 184, 192 };
size_t k;
+ struct hostapd_channel_data *p_chan, *s_chan;
+ const int ht40_plus = pri_chan < sec_chan;
- if (pri_chan == sec_chan || !sec_chan)
- return 1; /* HT40 not used */
+ p_chan = hw_get_channel_chan(mode, pri_chan, NULL);
+ if (!p_chan)
+ return 0;
+
+ if (pri_chan == sec_chan || !sec_chan) {
+ if (chan_pri_allowed(p_chan))
+ return 1; /* HT40 not used */
+
+ wpa_printf(MSG_ERROR, "Channel %d is not allowed as primary",
+ pri_chan);
+ return 0;
+ }
+
+ s_chan = hw_get_channel_chan(mode, sec_chan, NULL);
+ if (!s_chan)
+ return 0;
wpa_printf(MSG_DEBUG,
"HT40: control channel: %d secondary channel: %d",
@@ -103,16 +119,9 @@ int allowed_ht40_channel_pair(struct hostapd_hw_modes *mode, int pri_chan,
/* Verify that HT40 secondary channel is an allowed 20 MHz
* channel */
- ok = 0;
- for (j = 0; j < mode->num_channels; j++) {
- struct hostapd_channel_data *chan = &mode->channels[j];
- if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
- chan->chan == sec_chan) {
- ok = 1;
- break;
- }
- }
- if (!ok) {
+ if ((s_chan->flag & HOSTAPD_CHAN_DISABLED) ||
+ (ht40_plus && !(p_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P)) ||
+ (!ht40_plus && !(p_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40M))) {
wpa_printf(MSG_ERROR, "HT40 secondary channel %d not allowed",
sec_chan);
return 0;
@@ -390,8 +399,10 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
/* fall through */
case VHT_CHANWIDTH_80MHZ:
data->bandwidth = 80;
- if ((vht_oper_chwidth == 1 && center_segment1) ||
- (vht_oper_chwidth == 3 && !center_segment1) ||
+ if ((vht_oper_chwidth == VHT_CHANWIDTH_80MHZ &&
+ center_segment1) ||
+ (vht_oper_chwidth == VHT_CHANWIDTH_80P80MHZ &&
+ !center_segment1) ||
!sec_channel_offset)
return -1;
if (!center_segment0) {
@@ -455,3 +466,157 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
return 0;
}
+
+
+void set_disable_ht40(struct ieee80211_ht_capabilities *htcaps,
+ int disabled)
+{
+ /* Masking these out disables HT40 */
+ le16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
+ HT_CAP_INFO_SHORT_GI40MHZ);
+
+ if (disabled)
+ htcaps->ht_capabilities_info &= ~msk;
+ else
+ htcaps->ht_capabilities_info |= msk;
+}
+
+
+#ifdef CONFIG_IEEE80211AC
+
+static int _ieee80211ac_cap_check(u32 hw, u32 conf, u32 cap,
+ const char *name)
+{
+ u32 req_cap = conf & cap;
+
+ /*
+ * Make sure we support all requested capabilities.
+ * NOTE: We assume that 'cap' represents a capability mask,
+ * not a discrete value.
+ */
+ if ((hw & req_cap) != req_cap) {
+ wpa_printf(MSG_ERROR,
+ "Driver does not support configured VHT capability [%s]",
+ name);
+ return 0;
+ }
+ return 1;
+}
+
+
+static int ieee80211ac_cap_check_max(u32 hw, u32 conf, u32 mask,
+ unsigned int shift,
+ const char *name)
+{
+ u32 hw_max = hw & mask;
+ u32 conf_val = conf & mask;
+
+ if (conf_val > hw_max) {
+ wpa_printf(MSG_ERROR,
+ "Configured VHT capability [%s] exceeds max value supported by the driver (%d > %d)",
+ name, conf_val >> shift, hw_max >> shift);
+ return 0;
+ }
+ return 1;
+}
+
+
+int ieee80211ac_cap_check(u32 hw, u32 conf)
+{
+#define VHT_CAP_CHECK(cap) \
+ do { \
+ if (!_ieee80211ac_cap_check(hw, conf, cap, #cap)) \
+ return 0; \
+ } while (0)
+
+#define VHT_CAP_CHECK_MAX(cap) \
+ do { \
+ if (!ieee80211ac_cap_check_max(hw, conf, cap, cap ## _SHIFT, \
+ #cap)) \
+ return 0; \
+ } while (0)
+
+ VHT_CAP_CHECK_MAX(VHT_CAP_MAX_MPDU_LENGTH_MASK);
+ VHT_CAP_CHECK_MAX(VHT_CAP_SUPP_CHAN_WIDTH_MASK);
+ VHT_CAP_CHECK(VHT_CAP_RXLDPC);
+ VHT_CAP_CHECK(VHT_CAP_SHORT_GI_80);
+ VHT_CAP_CHECK(VHT_CAP_SHORT_GI_160);
+ VHT_CAP_CHECK(VHT_CAP_TXSTBC);
+ VHT_CAP_CHECK_MAX(VHT_CAP_RXSTBC_MASK);
+ VHT_CAP_CHECK(VHT_CAP_SU_BEAMFORMER_CAPABLE);
+ VHT_CAP_CHECK(VHT_CAP_SU_BEAMFORMEE_CAPABLE);
+ VHT_CAP_CHECK_MAX(VHT_CAP_BEAMFORMEE_STS_MAX);
+ VHT_CAP_CHECK_MAX(VHT_CAP_SOUNDING_DIMENSION_MAX);
+ VHT_CAP_CHECK(VHT_CAP_MU_BEAMFORMER_CAPABLE);
+ VHT_CAP_CHECK(VHT_CAP_MU_BEAMFORMEE_CAPABLE);
+ VHT_CAP_CHECK(VHT_CAP_VHT_TXOP_PS);
+ VHT_CAP_CHECK(VHT_CAP_HTC_VHT);
+ VHT_CAP_CHECK_MAX(VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX);
+ VHT_CAP_CHECK(VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB);
+ VHT_CAP_CHECK(VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB);
+ VHT_CAP_CHECK(VHT_CAP_RX_ANTENNA_PATTERN);
+ VHT_CAP_CHECK(VHT_CAP_TX_ANTENNA_PATTERN);
+
+#undef VHT_CAP_CHECK
+#undef VHT_CAP_CHECK_MAX
+
+ return 1;
+}
+
+#endif /* CONFIG_IEEE80211AC */
+
+
+u32 num_chan_to_bw(int num_chans)
+{
+ switch (num_chans) {
+ case 2:
+ case 4:
+ case 8:
+ return num_chans * 20;
+ default:
+ return 20;
+ }
+}
+
+
+/* check if BW is applicable for channel */
+int chan_bw_allowed(const struct hostapd_channel_data *chan, u32 bw,
+ int ht40_plus, int pri)
+{
+ u32 bw_mask;
+
+ switch (bw) {
+ case 20:
+ bw_mask = HOSTAPD_CHAN_WIDTH_20;
+ break;
+ case 40:
+ /* HT 40 MHz support declared only for primary channel,
+ * just skip 40 MHz secondary checking */
+ if (pri && ht40_plus)
+ bw_mask = HOSTAPD_CHAN_WIDTH_40P;
+ else if (pri && !ht40_plus)
+ bw_mask = HOSTAPD_CHAN_WIDTH_40M;
+ else
+ bw_mask = 0;
+ break;
+ case 80:
+ bw_mask = HOSTAPD_CHAN_WIDTH_80;
+ break;
+ case 160:
+ bw_mask = HOSTAPD_CHAN_WIDTH_160;
+ break;
+ default:
+ bw_mask = 0;
+ break;
+ }
+
+ return (chan->allowed_bw & bw_mask) == bw_mask;
+}
+
+
+/* check if channel is allowed to be used as primary */
+int chan_pri_allowed(const struct hostapd_channel_data *chan)
+{
+ return !(chan->flag & HOSTAPD_CHAN_DISABLED) &&
+ (chan->allowed_bw & HOSTAPD_CHAN_WIDTH_20);
+}
diff --git a/freebsd/contrib/wpa/src/common/hw_features_common.h b/freebsd/contrib/wpa/src/common/hw_features_common.h
index 7360b4e3..eb1f1c57 100644
--- a/freebsd/contrib/wpa/src/common/hw_features_common.h
+++ b/freebsd/contrib/wpa/src/common/hw_features_common.h
@@ -35,5 +35,13 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
int vht_enabled, int sec_channel_offset,
int vht_oper_chwidth, int center_segment0,
int center_segment1, u32 vht_caps);
+void set_disable_ht40(struct ieee80211_ht_capabilities *htcaps,
+ int disabled);
+int ieee80211ac_cap_check(u32 hw, u32 conf);
+
+u32 num_chan_to_bw(int num_chans);
+int chan_bw_allowed(const struct hostapd_channel_data *chan, u32 bw,
+ int ht40_plus, int pri);
+int chan_pri_allowed(const struct hostapd_channel_data *chan);
#endif /* HW_FEATURES_COMMON_H */
diff --git a/freebsd/contrib/wpa/src/common/ieee802_11_common.c b/freebsd/contrib/wpa/src/common/ieee802_11_common.c
index 286fdcf8..c6fc9019 100644
--- a/freebsd/contrib/wpa/src/common/ieee802_11_common.c
+++ b/freebsd/contrib/wpa/src/common/ieee802_11_common.c
@@ -2,7 +2,7 @@
/*
* IEEE 802.11 Common routines
- * Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -13,6 +13,7 @@
#include "common.h"
#include "defs.h"
#include "wpa_common.h"
+#include "drivers/driver.h"
#include "qca-vendor.h"
#include "ieee802_11_defs.h"
#include "ieee802_11_common.h"
@@ -122,6 +123,15 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
elems->mbo = pos;
elems->mbo_len = elen;
break;
+ case HS20_ROAMING_CONS_SEL_OUI_TYPE:
+ /* Hotspot 2.0 Roaming Consortium Selection */
+ elems->roaming_cons_sel = pos;
+ elems->roaming_cons_sel_len = elen;
+ break;
+ case MULTI_AP_OUI_TYPE:
+ elems->multi_ap = pos;
+ elems->multi_ap_len = elen;
+ break;
default:
wpa_printf(MSG_MSGDUMP, "Unknown WFA "
"information element ignored "
@@ -181,6 +191,108 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
}
+static int ieee802_11_parse_extension(const u8 *pos, size_t elen,
+ struct ieee802_11_elems *elems,
+ int show_errors)
+{
+ u8 ext_id;
+
+ if (elen < 1) {
+ if (show_errors) {
+ wpa_printf(MSG_MSGDUMP,
+ "short information element (Ext)");
+ }
+ return -1;
+ }
+
+ ext_id = *pos++;
+ elen--;
+
+ switch (ext_id) {
+ case WLAN_EID_EXT_ASSOC_DELAY_INFO:
+ if (elen != 1)
+ break;
+ elems->assoc_delay_info = pos;
+ break;
+ case WLAN_EID_EXT_FILS_REQ_PARAMS:
+ if (elen < 3)
+ break;
+ elems->fils_req_params = pos;
+ elems->fils_req_params_len = elen;
+ break;
+ case WLAN_EID_EXT_FILS_KEY_CONFIRM:
+ elems->fils_key_confirm = pos;
+ elems->fils_key_confirm_len = elen;
+ break;
+ case WLAN_EID_EXT_FILS_SESSION:
+ if (elen != FILS_SESSION_LEN)
+ break;
+ elems->fils_session = pos;
+ break;
+ case WLAN_EID_EXT_FILS_HLP_CONTAINER:
+ if (elen < 2 * ETH_ALEN)
+ break;
+ elems->fils_hlp = pos;
+ elems->fils_hlp_len = elen;
+ break;
+ case WLAN_EID_EXT_FILS_IP_ADDR_ASSIGN:
+ if (elen < 1)
+ break;
+ elems->fils_ip_addr_assign = pos;
+ elems->fils_ip_addr_assign_len = elen;
+ break;
+ case WLAN_EID_EXT_KEY_DELIVERY:
+ if (elen < WPA_KEY_RSC_LEN)
+ break;
+ elems->key_delivery = pos;
+ elems->key_delivery_len = elen;
+ break;
+ case WLAN_EID_EXT_FILS_WRAPPED_DATA:
+ elems->fils_wrapped_data = pos;
+ elems->fils_wrapped_data_len = elen;
+ break;
+ case WLAN_EID_EXT_FILS_PUBLIC_KEY:
+ if (elen < 1)
+ break;
+ elems->fils_pk = pos;
+ elems->fils_pk_len = elen;
+ break;
+ case WLAN_EID_EXT_FILS_NONCE:
+ if (elen != FILS_NONCE_LEN)
+ break;
+ elems->fils_nonce = pos;
+ break;
+ case WLAN_EID_EXT_OWE_DH_PARAM:
+ if (elen < 2)
+ break;
+ elems->owe_dh = pos;
+ elems->owe_dh_len = elen;
+ break;
+ case WLAN_EID_EXT_PASSWORD_IDENTIFIER:
+ elems->password_id = pos;
+ elems->password_id_len = elen;
+ break;
+ case WLAN_EID_EXT_HE_CAPABILITIES:
+ elems->he_capabilities = pos;
+ elems->he_capabilities_len = elen;
+ break;
+ case WLAN_EID_EXT_OCV_OCI:
+ elems->oci = pos;
+ elems->oci_len = elen;
+ break;
+ default:
+ if (show_errors) {
+ wpa_printf(MSG_MSGDUMP,
+ "IEEE 802.11 element parsing ignored unknown element extension (ext_id=%u elen=%u)",
+ ext_id, (unsigned int) elen);
+ }
+ return -1;
+ }
+
+ return 0;
+}
+
+
/**
* ieee802_11_parse_elems - Parse information elements in management frames
* @start: Pointer to the start of IEs
@@ -193,29 +305,17 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
struct ieee802_11_elems *elems,
int show_errors)
{
- size_t left = len;
- const u8 *pos = start;
+ const struct element *elem;
int unknown = 0;
os_memset(elems, 0, sizeof(*elems));
- while (left >= 2) {
- u8 id, elen;
+ if (!start)
+ return ParseOK;
- id = *pos++;
- elen = *pos++;
- left -= 2;
-
- if (elen > left) {
- if (show_errors) {
- wpa_printf(MSG_DEBUG, "IEEE 802.11 element "
- "parse failed (id=%d elen=%d "
- "left=%lu)",
- id, elen, (unsigned long) left);
- wpa_hexdump(MSG_MSGDUMP, "IEs", start, len);
- }
- return ParseFailed;
- }
+ for_each_element(elem, start, len) {
+ u8 id = elem->id, elen = elem->datalen;
+ const u8 *pos = elem->data;
switch (id) {
case WLAN_EID_SSID:
@@ -264,6 +364,10 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
elems->rsn_ie_len = elen;
break;
case WLAN_EID_PWR_CAPABILITY:
+ if (elen < 2)
+ break;
+ elems->power_capab = pos;
+ elems->power_capab_len = elen;
break;
case WLAN_EID_SUPPORTED_CHANNELS:
elems->supp_channels = pos;
@@ -359,8 +463,7 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
elems->mic = pos;
elems->mic_len = elen;
/* after mic everything is encrypted, so stop. */
- left = elen;
- break;
+ goto done;
case WLAN_EID_MULTI_BAND:
if (elems->mb_ies.nof_ies >= MAX_NOF_MB_IES_SUPPORTED) {
wpa_printf(MSG_MSGDUMP,
@@ -381,6 +484,35 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
elems->rrm_enabled = pos;
elems->rrm_enabled_len = elen;
break;
+ case WLAN_EID_CAG_NUMBER:
+ elems->cag_number = pos;
+ elems->cag_number_len = elen;
+ break;
+ case WLAN_EID_AP_CSN:
+ if (elen < 1)
+ break;
+ elems->ap_csn = pos;
+ break;
+ case WLAN_EID_FILS_INDICATION:
+ if (elen < 2)
+ break;
+ elems->fils_indic = pos;
+ elems->fils_indic_len = elen;
+ break;
+ case WLAN_EID_DILS:
+ if (elen < 2)
+ break;
+ elems->dils = pos;
+ elems->dils_len = elen;
+ break;
+ case WLAN_EID_FRAGMENT:
+ /* TODO */
+ break;
+ case WLAN_EID_EXTENSION:
+ if (ieee802_11_parse_extension(pos, elen, elems,
+ show_errors))
+ unknown++;
+ break;
default:
unknown++;
if (!show_errors)
@@ -390,35 +522,33 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
id, elen);
break;
}
-
- left -= elen;
- pos += elen;
}
- if (left)
+ if (!for_each_element_completed(elem, start, len)) {
+ if (show_errors) {
+ wpa_printf(MSG_DEBUG,
+ "IEEE 802.11 element parse failed @%d",
+ (int) (start + len - (const u8 *) elem));
+ wpa_hexdump(MSG_MSGDUMP, "IEs", start, len);
+ }
return ParseFailed;
+ }
+done:
return unknown ? ParseUnknown : ParseOK;
}
int ieee802_11_ie_count(const u8 *ies, size_t ies_len)
{
+ const struct element *elem;
int count = 0;
- const u8 *pos, *end;
if (ies == NULL)
return 0;
- pos = ies;
- end = ies + ies_len;
-
- while (end - pos >= 2) {
- if (2 + pos[1] > end - pos)
- break;
+ for_each_element(elem, ies, ies_len)
count++;
- pos += 2 + pos[1];
- }
return count;
}
@@ -428,24 +558,17 @@ struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
u32 oui_type)
{
struct wpabuf *buf;
- const u8 *end, *pos, *ie;
+ const struct element *elem, *found = NULL;
- pos = ies;
- end = ies + ies_len;
- ie = NULL;
-
- while (end - pos > 1) {
- if (2 + pos[1] > end - pos)
- return NULL;
- if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
- WPA_GET_BE32(&pos[2]) == oui_type) {
- ie = pos;
+ for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies, ies_len) {
+ if (elem->datalen >= 4 &&
+ WPA_GET_BE32(elem->data) == oui_type) {
+ found = elem;
break;
}
- pos += 2 + pos[1];
}
- if (ie == NULL)
+ if (!found)
return NULL; /* No specified vendor IE found */
buf = wpabuf_alloc(ies_len);
@@ -456,13 +579,9 @@ struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
* There may be multiple vendor IEs in the message, so need to
* concatenate their data fields.
*/
- while (end - pos > 1) {
- if (2 + pos[1] > end - pos)
- break;
- if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
- WPA_GET_BE32(&pos[2]) == oui_type)
- wpabuf_put_data(buf, pos + 6, pos[1] - 4);
- pos += 2 + pos[1];
+ for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies, ies_len) {
+ if (elem->datalen >= 4 && WPA_GET_BE32(elem->data) == oui_type)
+ wpabuf_put_data(buf, elem->data + 4, elem->datalen - 4);
}
return buf;
@@ -683,6 +802,25 @@ enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq,
return HOSTAPD_MODE_IEEE80211A;
}
+ /* 5 GHz, channels 52..64 */
+ if (freq >= 5260 && freq <= 5320) {
+ if ((freq - 5000) % 5)
+ return NUM_HOSTAPD_MODES;
+
+ if (vht_opclass)
+ *op_class = vht_opclass;
+ else if (sec_channel == 1)
+ *op_class = 119;
+ else if (sec_channel == -1)
+ *op_class = 120;
+ else
+ *op_class = 118;
+
+ *channel = (freq - 5000) / 5;
+
+ return HOSTAPD_MODE_IEEE80211A;
+ }
+
/* 5 GHz, channels 149..169 */
if (freq >= 5745 && freq <= 5845) {
if ((freq - 5000) % 5)
@@ -746,6 +884,41 @@ enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq,
}
+int ieee80211_chaninfo_to_channel(unsigned int freq, enum chan_width chanwidth,
+ int sec_channel, u8 *op_class, u8 *channel)
+{
+ int vht = CHAN_WIDTH_UNKNOWN;
+
+ switch (chanwidth) {
+ case CHAN_WIDTH_UNKNOWN:
+ case CHAN_WIDTH_20_NOHT:
+ case CHAN_WIDTH_20:
+ case CHAN_WIDTH_40:
+ vht = VHT_CHANWIDTH_USE_HT;
+ break;
+ case CHAN_WIDTH_80:
+ vht = VHT_CHANWIDTH_80MHZ;
+ break;
+ case CHAN_WIDTH_80P80:
+ vht = VHT_CHANWIDTH_80P80MHZ;
+ break;
+ case CHAN_WIDTH_160:
+ vht = VHT_CHANWIDTH_160MHZ;
+ break;
+ }
+
+ if (ieee80211_freq_to_channel_ext(freq, sec_channel, vht, op_class,
+ channel) == NUM_HOSTAPD_MODES) {
+ wpa_printf(MSG_WARNING,
+ "Cannot determine operating class and channel (freq=%u chanwidth=%d sec_channel=%d)",
+ freq, chanwidth, sec_channel);
+ return -1;
+ }
+
+ return 0;
+}
+
+
static const char *const us_op_class_cc[] = {
"US", "CA", NULL
};
@@ -983,7 +1156,7 @@ static int ieee80211_chan_to_freq_global(u8 op_class, u8 chan)
return -1;
return 5000 + 5 * chan;
case 129: /* center freqs 50, 114; 160 MHz */
- if (chan < 50 || chan > 114)
+ if (chan < 36 || chan > 128)
return -1;
return 5000 + 5 * chan;
case 180: /* 60 GHz band, channels 1..4 */
@@ -1033,10 +1206,24 @@ int ieee80211_chan_to_freq(const char *country, u8 op_class, u8 chan)
}
-int ieee80211_is_dfs(int freq)
+int ieee80211_is_dfs(int freq, const struct hostapd_hw_modes *modes,
+ u16 num_modes)
{
- /* TODO: this could be more accurate to better cover all domains */
- return (freq >= 5260 && freq <= 5320) || (freq >= 5500 && freq <= 5700);
+ int i, j;
+
+ if (!modes || !num_modes)
+ return (freq >= 5260 && freq <= 5320) ||
+ (freq >= 5500 && freq <= 5700);
+
+ for (i = 0; i < num_modes; i++) {
+ for (j = 0; j < modes[i].num_channels; j++) {
+ if (modes[i].channels[j].freq == freq &&
+ (modes[i].channels[j].flag & HOSTAPD_CHAN_RADAR))
+ return 1;
+ }
+ }
+
+ return 0;
}
@@ -1133,27 +1320,27 @@ const char * fc2str(u16 fc)
int mb_ies_info_by_ies(struct mb_ies_info *info, const u8 *ies_buf,
size_t ies_len)
{
+ const struct element *elem;
+
os_memset(info, 0, sizeof(*info));
- while (ies_buf && ies_len >= 2 &&
- info->nof_ies < MAX_NOF_MB_IES_SUPPORTED) {
- size_t len = 2 + ies_buf[1];
+ if (!ies_buf)
+ return 0;
- if (len > ies_len) {
- wpa_hexdump(MSG_DEBUG, "Truncated IEs",
- ies_buf, ies_len);
- return -1;
- }
+ for_each_element_id(elem, WLAN_EID_MULTI_BAND, ies_buf, ies_len) {
+ if (info->nof_ies >= MAX_NOF_MB_IES_SUPPORTED)
+ return 0;
- if (ies_buf[0] == WLAN_EID_MULTI_BAND) {
- wpa_printf(MSG_DEBUG, "MB IE of %zu bytes found", len);
- info->ies[info->nof_ies].ie = ies_buf + 2;
- info->ies[info->nof_ies].ie_len = ies_buf[1];
- info->nof_ies++;
- }
+ wpa_printf(MSG_DEBUG, "MB IE of %u bytes found",
+ elem->datalen + 2);
+ info->ies[info->nof_ies].ie = elem->data;
+ info->ies[info->nof_ies].ie_len = elem->datalen;
+ info->nof_ies++;
+ }
- ies_len -= len;
- ies_buf += len;
+ if (!for_each_element_completed(elem, ies_buf, ies_len)) {
+ wpa_hexdump(MSG_DEBUG, "Truncated IEs", ies_buf, ies_len);
+ return -1;
}
return 0;
@@ -1276,21 +1463,50 @@ size_t global_op_class_size = ARRAY_SIZE(global_op_class);
*/
const u8 * get_ie(const u8 *ies, size_t len, u8 eid)
{
- const u8 *end;
+ const struct element *elem;
if (!ies)
return NULL;
- end = ies + len;
+ for_each_element_id(elem, eid, ies, len)
+ return &elem->id;
- while (end - ies > 1) {
- if (2 + ies[1] > end - ies)
- break;
+ return NULL;
+}
- if (ies[0] == eid)
- return ies;
- ies += 2 + ies[1];
+/**
+ * get_ie_ext - Fetch a specified extended information element from IEs buffer
+ * @ies: Information elements buffer
+ * @len: Information elements buffer length
+ * @ext: Information element extension identifier (WLAN_EID_EXT_*)
+ * Returns: Pointer to the information element (id field) or %NULL if not found
+ *
+ * This function returns the first matching information element in the IEs
+ * buffer or %NULL in case the element is not found.
+ */
+const u8 * get_ie_ext(const u8 *ies, size_t len, u8 ext)
+{
+ const struct element *elem;
+
+ if (!ies)
+ return NULL;
+
+ for_each_element_extid(elem, ext, ies, len)
+ return &elem->id;
+
+ return NULL;
+}
+
+
+const u8 * get_vendor_ie(const u8 *ies, size_t len, u32 vendor_type)
+{
+ const struct element *elem;
+
+ for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies, len) {
+ if (elem->datalen >= 4 &&
+ vendor_type == WPA_GET_BE32(elem->data))
+ return &elem->id;
}
return NULL;
@@ -1319,3 +1535,299 @@ size_t mbo_add_ie(u8 *buf, size_t len, const u8 *attr, size_t attr_len)
return 6 + attr_len;
}
+
+
+size_t add_multi_ap_ie(u8 *buf, size_t len, u8 value)
+{
+ u8 *pos = buf;
+
+ if (len < 9)
+ return 0;
+
+ *pos++ = WLAN_EID_VENDOR_SPECIFIC;
+ *pos++ = 7; /* len */
+ WPA_PUT_BE24(pos, OUI_WFA);
+ pos += 3;
+ *pos++ = MULTI_AP_OUI_TYPE;
+ *pos++ = MULTI_AP_SUB_ELEM_TYPE;
+ *pos++ = 1; /* len */
+ *pos++ = value;
+
+ return pos - buf;
+}
+
+
+static const struct country_op_class us_op_class[] = {
+ { 1, 115 },
+ { 2, 118 },
+ { 3, 124 },
+ { 4, 121 },
+ { 5, 125 },
+ { 12, 81 },
+ { 22, 116 },
+ { 23, 119 },
+ { 24, 122 },
+ { 25, 126 },
+ { 26, 126 },
+ { 27, 117 },
+ { 28, 120 },
+ { 29, 123 },
+ { 30, 127 },
+ { 31, 127 },
+ { 32, 83 },
+ { 33, 84 },
+ { 34, 180 },
+};
+
+static const struct country_op_class eu_op_class[] = {
+ { 1, 115 },
+ { 2, 118 },
+ { 3, 121 },
+ { 4, 81 },
+ { 5, 116 },
+ { 6, 119 },
+ { 7, 122 },
+ { 8, 117 },
+ { 9, 120 },
+ { 10, 123 },
+ { 11, 83 },
+ { 12, 84 },
+ { 17, 125 },
+ { 18, 180 },
+};
+
+static const struct country_op_class jp_op_class[] = {
+ { 1, 115 },
+ { 30, 81 },
+ { 31, 82 },
+ { 32, 118 },
+ { 33, 118 },
+ { 34, 121 },
+ { 35, 121 },
+ { 36, 116 },
+ { 37, 119 },
+ { 38, 119 },
+ { 39, 122 },
+ { 40, 122 },
+ { 41, 117 },
+ { 42, 120 },
+ { 43, 120 },
+ { 44, 123 },
+ { 45, 123 },
+ { 56, 83 },
+ { 57, 84 },
+ { 58, 121 },
+ { 59, 180 },
+};
+
+static const struct country_op_class cn_op_class[] = {
+ { 1, 115 },
+ { 2, 118 },
+ { 3, 125 },
+ { 4, 116 },
+ { 5, 119 },
+ { 6, 126 },
+ { 7, 81 },
+ { 8, 83 },
+ { 9, 84 },
+};
+
+static u8
+global_op_class_from_country_array(u8 op_class, size_t array_size,
+ const struct country_op_class *country_array)
+{
+ size_t i;
+
+ for (i = 0; i < array_size; i++) {
+ if (country_array[i].country_op_class == op_class)
+ return country_array[i].global_op_class;
+ }
+
+ return 0;
+}
+
+
+u8 country_to_global_op_class(const char *country, u8 op_class)
+{
+ const struct country_op_class *country_array;
+ size_t size;
+ u8 g_op_class;
+
+ if (country_match(us_op_class_cc, country)) {
+ country_array = us_op_class;
+ size = ARRAY_SIZE(us_op_class);
+ } else if (country_match(eu_op_class_cc, country)) {
+ country_array = eu_op_class;
+ size = ARRAY_SIZE(eu_op_class);
+ } else if (country_match(jp_op_class_cc, country)) {
+ country_array = jp_op_class;
+ size = ARRAY_SIZE(jp_op_class);
+ } else if (country_match(cn_op_class_cc, country)) {
+ country_array = cn_op_class;
+ size = ARRAY_SIZE(cn_op_class);
+ } else {
+ /*
+ * Countries that do not match any of the above countries use
+ * global operating classes
+ */
+ return op_class;
+ }
+
+ g_op_class = global_op_class_from_country_array(op_class, size,
+ country_array);
+
+ /*
+ * If the given operating class did not match any of the country's
+ * operating classes, assume that global operating class is used.
+ */
+ return g_op_class ? g_op_class : op_class;
+}
+
+
+const struct oper_class_map * get_oper_class(const char *country, u8 op_class)
+{
+ const struct oper_class_map *op;
+
+ if (country)
+ op_class = country_to_global_op_class(country, op_class);
+
+ op = &global_op_class[0];
+ while (op->op_class && op->op_class != op_class)
+ op++;
+
+ if (!op->op_class)
+ return NULL;
+
+ return op;
+}
+
+
+int oper_class_bw_to_int(const struct oper_class_map *map)
+{
+ switch (map->bw) {
+ case BW20:
+ return 20;
+ case BW40PLUS:
+ case BW40MINUS:
+ return 40;
+ case BW80:
+ return 80;
+ case BW80P80:
+ case BW160:
+ return 160;
+ case BW2160:
+ return 2160;
+ default:
+ return 0;
+ }
+}
+
+
+int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
+ size_t nei_rep_len)
+{
+ u8 *nei_pos = nei_rep;
+ const char *end;
+
+ /*
+ * BSS Transition Candidate List Entries - Neighbor Report elements
+ * neighbor=<BSSID>,<BSSID Information>,<Operating Class>,
+ * <Channel Number>,<PHY Type>[,<hexdump of Optional Subelements>]
+ */
+ while (pos) {
+ u8 *nei_start;
+ long int val;
+ char *endptr, *tmp;
+
+ pos = os_strstr(pos, " neighbor=");
+ if (!pos)
+ break;
+ if (nei_pos + 15 > nei_rep + nei_rep_len) {
+ wpa_printf(MSG_DEBUG,
+ "Not enough room for additional neighbor");
+ return -1;
+ }
+ pos += 10;
+
+ nei_start = nei_pos;
+ *nei_pos++ = WLAN_EID_NEIGHBOR_REPORT;
+ nei_pos++; /* length to be filled in */
+
+ if (hwaddr_aton(pos, nei_pos)) {
+ wpa_printf(MSG_DEBUG, "Invalid BSSID");
+ return -1;
+ }
+ nei_pos += ETH_ALEN;
+ pos += 17;
+ if (*pos != ',') {
+ wpa_printf(MSG_DEBUG, "Missing BSSID Information");
+ return -1;
+ }
+ pos++;
+
+ val = strtol(pos, &endptr, 0);
+ WPA_PUT_LE32(nei_pos, val);
+ nei_pos += 4;
+ if (*endptr != ',') {
+ wpa_printf(MSG_DEBUG, "Missing Operating Class");
+ return -1;
+ }
+ pos = endptr + 1;
+
+ *nei_pos++ = atoi(pos); /* Operating Class */
+ pos = os_strchr(pos, ',');
+ if (pos == NULL) {
+ wpa_printf(MSG_DEBUG, "Missing Channel Number");
+ return -1;
+ }
+ pos++;
+
+ *nei_pos++ = atoi(pos); /* Channel Number */
+ pos = os_strchr(pos, ',');
+ if (pos == NULL) {
+ wpa_printf(MSG_DEBUG, "Missing PHY Type");
+ return -1;
+ }
+ pos++;
+
+ *nei_pos++ = atoi(pos); /* PHY Type */
+ end = os_strchr(pos, ' ');
+ tmp = os_strchr(pos, ',');
+ if (tmp && (!end || tmp < end)) {
+ /* Optional Subelements (hexdump) */
+ size_t len;
+
+ pos = tmp + 1;
+ end = os_strchr(pos, ' ');
+ if (end)
+ len = end - pos;
+ else
+ len = os_strlen(pos);
+ if (nei_pos + len / 2 > nei_rep + nei_rep_len) {
+ wpa_printf(MSG_DEBUG,
+ "Not enough room for neighbor subelements");
+ return -1;
+ }
+ if (len & 0x01 ||
+ hexstr2bin(pos, nei_pos, len / 2) < 0) {
+ wpa_printf(MSG_DEBUG,
+ "Invalid neighbor subelement info");
+ return -1;
+ }
+ nei_pos += len / 2;
+ pos = end;
+ }
+
+ nei_start[1] = nei_pos - nei_start - 2;
+ }
+
+ return nei_pos - nei_rep;
+}
+
+
+int ieee802_11_ext_capab(const u8 *ie, unsigned int capab)
+{
+ if (!ie || ie[1] <= capab / 8)
+ return 0;
+ return !!(ie[2 + capab / 8] & BIT(capab % 8));
+}
diff --git a/freebsd/contrib/wpa/src/common/ieee802_11_common.h b/freebsd/contrib/wpa/src/common/ieee802_11_common.h
index 42f39096..d41bd39e 100644
--- a/freebsd/contrib/wpa/src/common/ieee802_11_common.h
+++ b/freebsd/contrib/wpa/src/common/ieee802_11_common.h
@@ -1,6 +1,6 @@
/*
* IEEE 802.11 Common routines
- * Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -10,6 +10,15 @@
#define IEEE802_11_COMMON_H
#include "defs.h"
+#include "ieee802_11_defs.h"
+
+struct element {
+ u8 id;
+ u8 datalen;
+ u8 data[];
+} STRUCT_PACKED;
+
+struct hostapd_hw_modes;
#define MAX_NOF_MB_IES_SUPPORTED 5
@@ -64,6 +73,27 @@ struct ieee802_11_elems {
const u8 *pref_freq_list;
const u8 *supp_op_classes;
const u8 *rrm_enabled;
+ const u8 *cag_number;
+ const u8 *ap_csn;
+ const u8 *fils_indic;
+ const u8 *dils;
+ const u8 *assoc_delay_info;
+ const u8 *fils_req_params;
+ const u8 *fils_key_confirm;
+ const u8 *fils_session;
+ const u8 *fils_hlp;
+ const u8 *fils_ip_addr_assign;
+ const u8 *key_delivery;
+ const u8 *fils_wrapped_data;
+ const u8 *fils_pk;
+ const u8 *fils_nonce;
+ const u8 *owe_dh;
+ const u8 *power_capab;
+ const u8 *roaming_cons_sel;
+ const u8 *password_id;
+ const u8 *oci;
+ const u8 *multi_ap;
+ const u8 *he_capabilities;
u8 ssid_len;
u8 supp_rates_len;
@@ -96,6 +126,23 @@ struct ieee802_11_elems {
u8 pref_freq_list_len;
u8 supp_op_classes_len;
u8 rrm_enabled_len;
+ u8 cag_number_len;
+ u8 fils_indic_len;
+ u8 dils_len;
+ u8 fils_req_params_len;
+ u8 fils_key_confirm_len;
+ u8 fils_hlp_len;
+ u8 fils_ip_addr_assign_len;
+ u8 key_delivery_len;
+ u8 fils_wrapped_data_len;
+ u8 fils_pk_len;
+ u8 owe_dh_len;
+ u8 power_capab_len;
+ u8 roaming_cons_sel_len;
+ u8 password_id_len;
+ u8 oci_len;
+ u8 multi_ap_len;
+ u8 he_capabilities_len;
struct mb_ies_info mb_ies;
};
@@ -126,7 +173,10 @@ int ieee80211_chan_to_freq(const char *country, u8 op_class, u8 chan);
enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq,
int sec_channel, int vht,
u8 *op_class, u8 *channel);
-int ieee80211_is_dfs(int freq);
+int ieee80211_chaninfo_to_channel(unsigned int freq, enum chan_width chanwidth,
+ int sec_channel, u8 *op_class, u8 *channel);
+int ieee80211_is_dfs(int freq, const struct hostapd_hw_modes *modes,
+ u16 num_modes);
enum phy_type ieee80211_get_phy_type(int freq, int ht, int vht);
int supp_rates_11b_only(struct ieee802_11_elems *elems);
@@ -150,7 +200,73 @@ extern const struct oper_class_map global_op_class[];
extern size_t global_op_class_size;
const u8 * get_ie(const u8 *ies, size_t len, u8 eid);
+const u8 * get_ie_ext(const u8 *ies, size_t len, u8 ext);
+const u8 * get_vendor_ie(const u8 *ies, size_t len, u32 vendor_type);
size_t mbo_add_ie(u8 *buf, size_t len, const u8 *attr, size_t attr_len);
+size_t add_multi_ap_ie(u8 *buf, size_t len, u8 value);
+
+struct country_op_class {
+ u8 country_op_class;
+ u8 global_op_class;
+};
+
+u8 country_to_global_op_class(const char *country, u8 op_class);
+
+const struct oper_class_map * get_oper_class(const char *country, u8 op_class);
+int oper_class_bw_to_int(const struct oper_class_map *map);
+
+int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
+ size_t nei_rep_len);
+
+int ieee802_11_ext_capab(const u8 *ie, unsigned int capab);
+
+/* element iteration helpers */
+#define for_each_element(_elem, _data, _datalen) \
+ for (_elem = (const struct element *) (_data); \
+ (const u8 *) (_data) + (_datalen) - (const u8 *) _elem >= \
+ (int) sizeof(*_elem) && \
+ (const u8 *) (_data) + (_datalen) - (const u8 *) _elem >= \
+ (int) sizeof(*_elem) + _elem->datalen; \
+ _elem = (const struct element *) (_elem->data + _elem->datalen))
+
+#define for_each_element_id(element, _id, data, datalen) \
+ for_each_element(element, data, datalen) \
+ if (element->id == (_id))
+
+#define for_each_element_extid(element, extid, _data, _datalen) \
+ for_each_element(element, _data, _datalen) \
+ if (element->id == WLAN_EID_EXTENSION && \
+ element->datalen > 0 && \
+ element->data[0] == (extid))
+
+#define for_each_subelement(sub, element) \
+ for_each_element(sub, (element)->data, (element)->datalen)
+
+#define for_each_subelement_id(sub, id, element) \
+ for_each_element_id(sub, id, (element)->data, (element)->datalen)
+
+#define for_each_subelement_extid(sub, extid, element) \
+ for_each_element_extid(sub, extid, (element)->data, (element)->datalen)
+
+/**
+ * for_each_element_completed - Determine if element parsing consumed all data
+ * @element: Element pointer after for_each_element() or friends
+ * @data: Same data pointer as passed to for_each_element() or friends
+ * @datalen: Same data length as passed to for_each_element() or friends
+ *
+ * This function returns 1 if all the data was parsed or considered
+ * while walking the elements. Only use this if your for_each_element()
+ * loop cannot be broken out of, otherwise it always returns 0.
+ *
+ * If some data was malformed, this returns %false since the last parsed
+ * element will not fill the whole remaining data.
+ */
+static inline int for_each_element_completed(const struct element *element,
+ const void *data, size_t datalen)
+{
+ return (const u8 *) element == (const u8 *) data + datalen;
+}
+
#endif /* IEEE802_11_COMMON_H */
diff --git a/freebsd/contrib/wpa/src/common/ieee802_11_defs.h b/freebsd/contrib/wpa/src/common/ieee802_11_defs.h
index d453aec7..adaa8931 100644
--- a/freebsd/contrib/wpa/src/common/ieee802_11_defs.h
+++ b/freebsd/contrib/wpa/src/common/ieee802_11_defs.h
@@ -1,6 +1,6 @@
/*
* IEEE 802.11 Frame type definitions
- * Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi>
* Copyright (c) 2007-2008 Intel Corporation
*
* This software may be distributed under the terms of the BSD license.
@@ -81,6 +81,9 @@
#define WLAN_AUTH_SHARED_KEY 1
#define WLAN_AUTH_FT 2
#define WLAN_AUTH_SAE 3
+#define WLAN_AUTH_FILS_SK 4
+#define WLAN_AUTH_FILS_SK_PFS 5
+#define WLAN_AUTH_FILS_PK 6
#define WLAN_AUTH_LEAP 128
#define WLAN_AUTH_CHALLENGE_LEN 128
@@ -102,7 +105,7 @@
#define WLAN_CAPABILITY_DELAYED_BLOCK_ACK BIT(14)
#define WLAN_CAPABILITY_IMM_BLOCK_ACK BIT(15)
-/* Status codes (IEEE 802.11-2007, 7.3.1.9, Table 7-23) */
+/* Status codes (IEEE Std 802.11-2016, 9.4.1.9, Table 9-46) */
#define WLAN_STATUS_SUCCESS 0
#define WLAN_STATUS_UNSPECIFIED_FAILURE 1
#define WLAN_STATUS_TDLS_WAKEUP_ALTERNATE 2
@@ -119,27 +122,23 @@
#define WLAN_STATUS_AUTH_TIMEOUT 16
#define WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA 17
#define WLAN_STATUS_ASSOC_DENIED_RATES 18
-/* IEEE 802.11b */
#define WLAN_STATUS_ASSOC_DENIED_NOSHORT 19
-#define WLAN_STATUS_ASSOC_DENIED_NOPBCC 20
-#define WLAN_STATUS_ASSOC_DENIED_NOAGILITY 21
-/* IEEE 802.11h */
#define WLAN_STATUS_SPEC_MGMT_REQUIRED 22
#define WLAN_STATUS_PWR_CAPABILITY_NOT_VALID 23
#define WLAN_STATUS_SUPPORTED_CHANNEL_NOT_VALID 24
-/* IEEE 802.11g */
#define WLAN_STATUS_ASSOC_DENIED_NO_SHORT_SLOT_TIME 25
-#define WLAN_STATUS_ASSOC_DENIED_NO_DSSS_OFDM 26
#define WLAN_STATUS_ASSOC_DENIED_NO_HT 27
#define WLAN_STATUS_R0KH_UNREACHABLE 28
#define WLAN_STATUS_ASSOC_DENIED_NO_PCO 29
-/* IEEE 802.11w */
#define WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY 30
#define WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION 31
#define WLAN_STATUS_UNSPECIFIED_QOS_FAILURE 32
+#define WLAN_STATUS_DENIED_INSUFFICIENT_BANDWIDTH 33
+#define WLAN_STATUS_DENIED_POOR_CHANNEL_CONDITIONS 34
+#define WLAN_STATUS_DENIED_QOS_NOT_SUPPORTED 35
#define WLAN_STATUS_REQUEST_DECLINED 37
#define WLAN_STATUS_INVALID_PARAMETERS 38
-/* IEEE 802.11i */
+#define WLAN_STATUS_REJECTED_WITH_SUGGESTED_CHANGES 39
#define WLAN_STATUS_INVALID_IE 40
#define WLAN_STATUS_GROUP_CIPHER_NOT_VALID 41
#define WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID 42
@@ -152,11 +151,13 @@
#define WLAN_STATUS_DEST_STA_NOT_PRESENT 49
#define WLAN_STATUS_DEST_STA_NOT_QOS_STA 50
#define WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE 51
-/* IEEE 802.11r */
#define WLAN_STATUS_INVALID_FT_ACTION_FRAME_COUNT 52
#define WLAN_STATUS_INVALID_PMKID 53
#define WLAN_STATUS_INVALID_MDIE 54
#define WLAN_STATUS_INVALID_FTIE 55
+#define WLAN_STATUS_REQUESTED_TCLAS_NOT_SUPPORTED 56
+#define WLAN_STATUS_INSUFFICIENT_TCLAS_PROCESSING_RESOURCES 57
+#define WLAN_STATUS_TRY_ANOTHER_BSS 58
#define WLAN_STATUS_GAS_ADV_PROTO_NOT_SUPPORTED 59
#define WLAN_STATUS_NO_OUTSTANDING_GAS_REQ 60
#define WLAN_STATUS_GAS_RESP_NOT_RECEIVED 61
@@ -167,16 +168,44 @@
#define WLAN_STATUS_REQ_REFUSED_SSPN 67
#define WLAN_STATUS_REQ_REFUSED_UNAUTH_ACCESS 68
#define WLAN_STATUS_INVALID_RSNIE 72
+#define WLAN_STATUS_U_APSD_COEX_NOT_SUPPORTED 73
+#define WLAN_STATUS_U_APSD_COEX_MODE_NOT_SUPPORTED 74
+#define WLAN_STATUS_BAD_INTERVAL_WITH_U_APSD_COEX 75
#define WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ 76
#define WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED 77
+#define WLAN_STATUS_CANNOT_FIND_ALT_TBTT 78
#define WLAN_STATUS_TRANSMISSION_FAILURE 79
+#define WLAN_STATUS_REQ_TCLAS_NOT_SUPPORTED 80
+#define WLAN_STATUS_TCLAS_RESOURCES_EXCHAUSTED 81
#define WLAN_STATUS_REJECTED_WITH_SUGGESTED_BSS_TRANSITION 82
+#define WLAN_STATUS_REJECT_WITH_SCHEDULE 83
+#define WLAN_STATUS_REJECT_NO_WAKEUP_SPECIFIED 84
+#define WLAN_STATUS_SUCCESS_POWER_SAVE_MODE 85
#define WLAN_STATUS_PENDING_ADMITTING_FST_SESSION 86
+#define WLAN_STATUS_PERFORMING_FST_NOW 87
+#define WLAN_STATUS_PENDING_GAP_IN_BA_WINDOW 88
+#define WLAN_STATUS_REJECT_U_PID_SETTING 89
+#define WLAN_STATUS_REFUSED_EXTERNAL_REASON 92
+#define WLAN_STATUS_REFUSED_AP_OUT_OF_MEMORY 93
+#define WLAN_STATUS_REJECTED_EMERGENCY_SERVICE_NOT_SUPPORTED 94
#define WLAN_STATUS_QUERY_RESP_OUTSTANDING 95
+#define WLAN_STATUS_REJECT_DSE_BAND 96
+#define WLAN_STATUS_TCLAS_PROCESSING_TERMINATED 97
+#define WLAN_STATUS_TS_SCHEDULE_CONFLICT 98
#define WLAN_STATUS_DENIED_WITH_SUGGESTED_BAND_AND_CHANNEL 99
+#define WLAN_STATUS_MCCAOP_RESERVATION_CONFLICT 100
+#define WLAN_STATUS_MAF_LIMIT_EXCEEDED 101
+#define WLAN_STATUS_MCCA_TRACK_LIMIT_EXCEEDED 102
+#define WLAN_STATUS_DENIED_DUE_TO_SPECTRUM_MANAGEMENT 103
#define WLAN_STATUS_ASSOC_DENIED_NO_VHT 104
-
-/* Reason codes (IEEE 802.11-2007, 7.3.1.7, Table 7-22) */
+#define WLAN_STATUS_ENABLEMENT_DENIED 105
+#define WLAN_STATUS_RESTRICTION_FROM_AUTHORIZED_GDB 106
+#define WLAN_STATUS_AUTHORIZATION_DEENABLED 107
+#define WLAN_STATUS_FILS_AUTHENTICATION_FAILURE 112
+#define WLAN_STATUS_UNKNOWN_AUTHENTICATION_SERVER 113
+#define WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER 123
+
+/* Reason codes (IEEE Std 802.11-2016, 9.4.1.7, Table 9-45) */
#define WLAN_REASON_UNSPECIFIED 1
#define WLAN_REASON_PREV_AUTH_NOT_VALID 2
#define WLAN_REASON_DEAUTH_LEAVING 3
@@ -186,10 +215,9 @@
#define WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA 7
#define WLAN_REASON_DISASSOC_STA_HAS_LEFT 8
#define WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH 9
-/* IEEE 802.11h */
#define WLAN_REASON_PWR_CAPABILITY_NOT_VALID 10
#define WLAN_REASON_SUPPORTED_CHANNEL_NOT_VALID 11
-/* IEEE 802.11i */
+#define WLAN_REASON_BSS_TRANSITION_DISASSOC 12
#define WLAN_REASON_INVALID_IE 13
#define WLAN_REASON_MICHAEL_MIC_FAILURE 14
#define WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT 15
@@ -204,9 +232,26 @@
#define WLAN_REASON_CIPHER_SUITE_REJECTED 24
#define WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE 25
#define WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED 26
-/* IEEE 802.11e */
+#define WLAN_REASON_SSP_REQUESTED_DISASSOC 27
+#define WLAN_REASON_NO_SSP_ROAMING_AGREEMENT 28
+#define WLAN_REASON_BAD_CIPHER_OR_AKM 29
+#define WLAN_REASON_NOT_AUTHORIZED_THIS_LOCATION 30
+#define WLAN_REASON_SERVICE_CHANGE_PRECLUDES_TS 31
+#define WLAN_REASON_UNSPECIFIED_QOS_REASON 32
+#define WLAN_REASON_NOT_ENOUGH_BANDWIDTH 33
#define WLAN_REASON_DISASSOC_LOW_ACK 34
-/* IEEE 802.11s */
+#define WLAN_REASON_EXCEEDED_TXOP 35
+#define WLAN_REASON_STA_LEAVING 36
+#define WLAN_REASON_END_TS_BA_DLS 37
+#define WLAN_REASON_UNKNOWN_TS_BA 38
+#define WLAN_REASON_TIMEOUT 39
+#define WLAN_REASON_PEERKEY_MISMATCH 45
+#define WLAN_REASON_AUTHORIZED_ACCESS_LIMIT_REACHED 46
+#define WLAN_REASON_EXTERNAL_SERVICE_REQUIREMENTS 47
+#define WLAN_REASON_INVALID_FT_ACTION_FRAME_COUNT 48
+#define WLAN_REASON_INVALID_PMKID 49
+#define WLAN_REASON_INVALID_MDE 50
+#define WLAN_REASON_INVALID_FTE 51
#define WLAN_REASON_MESH_PEERING_CANCELLED 52
#define WLAN_REASON_MESH_MAX_PEERS 53
#define WLAN_REASON_MESH_CONFIG_POLICY_VIOLATION 54
@@ -216,20 +261,29 @@
#define WLAN_REASON_MESH_INVALID_GTK 58
#define WLAN_REASON_MESH_INCONSISTENT_PARAMS 59
#define WLAN_REASON_MESH_INVALID_SECURITY_CAP 60
+#define WLAN_REASON_MESH_PATH_ERROR_NO_PROXY_INFO 61
+#define WLAN_REASON_MESH_PATH_ERROR_NO_FORWARDING_INFO 62
+#define WLAN_REASON_MESH_PATH_ERROR_DEST_UNREACHABLE 63
+#define WLAN_REASON_MAC_ADDRESS_ALREADY_EXISTS_IN_MBSS 64
+#define WLAN_REASON_MESH_CHANNEL_SWITCH_REGULATORY_REQ 65
+#define WLAN_REASON_MESH_CHANNEL_SWITCH_UNSPECIFIED 66
-/* Information Element IDs */
+/* Information Element IDs (IEEE Std 802.11-2016, 9.4.2.1, Table 9-77) */
#define WLAN_EID_SSID 0
#define WLAN_EID_SUPP_RATES 1
-#define WLAN_EID_FH_PARAMS 2
#define WLAN_EID_DS_PARAMS 3
#define WLAN_EID_CF_PARAMS 4
#define WLAN_EID_TIM 5
#define WLAN_EID_IBSS_PARAMS 6
#define WLAN_EID_COUNTRY 7
+#define WLAN_EID_REQUEST 10
#define WLAN_EID_BSS_LOAD 11
+#define WLAN_EID_EDCA_PARAM_SET 12
+#define WLAN_EID_TSPEC 13
+#define WLAN_EID_TCLAS 14
+#define WLAN_EID_SCHEDULE 15
#define WLAN_EID_CHALLENGE 16
-/* EIDs defined by IEEE 802.11h - START */
#define WLAN_EID_PWR_CONSTRAINT 32
#define WLAN_EID_PWR_CAPABILITY 33
#define WLAN_EID_TPC_REQUEST 34
@@ -238,50 +292,139 @@
#define WLAN_EID_CHANNEL_SWITCH 37
#define WLAN_EID_MEASURE_REQUEST 38
#define WLAN_EID_MEASURE_REPORT 39
-#define WLAN_EID_QUITE 40
+#define WLAN_EID_QUIET 40
#define WLAN_EID_IBSS_DFS 41
-/* EIDs defined by IEEE 802.11h - END */
#define WLAN_EID_ERP_INFO 42
+#define WLAN_EID_TS_DELAY 43
+#define WLAN_EID_TCLAS_PROCESSING 44
#define WLAN_EID_HT_CAP 45
#define WLAN_EID_QOS 46
#define WLAN_EID_RSN 48
#define WLAN_EID_EXT_SUPP_RATES 50
+#define WLAN_EID_AP_CHANNEL_REPORT 51
#define WLAN_EID_NEIGHBOR_REPORT 52
+#define WLAN_EID_RCPI 53
#define WLAN_EID_MOBILITY_DOMAIN 54
#define WLAN_EID_FAST_BSS_TRANSITION 55
#define WLAN_EID_TIMEOUT_INTERVAL 56
#define WLAN_EID_RIC_DATA 57
+#define WLAN_EID_DSE_REGISTERED_LOCATION 58
#define WLAN_EID_SUPPORTED_OPERATING_CLASSES 59
#define WLAN_EID_EXT_CHANSWITCH_ANN 60
#define WLAN_EID_HT_OPERATION 61
#define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62
-#define WLAN_EID_WAPI 68
+#define WLAN_EID_BSS_AVERAGE_ACCESS_DELAY 63
+#define WLAN_EID_ANTENNA 64
+#define WLAN_EID_RSNI 65
+#define WLAN_EID_MEASUREMENT_PILOT_TRANSMISSION 66
+#define WLAN_EID_BSS_AVAILABLE_ADM_CAPA 67
+#define WLAN_EID_BSS_AC_ACCESS_DELAY 68 /* note: also used by WAPI */
#define WLAN_EID_TIME_ADVERTISEMENT 69
#define WLAN_EID_RRM_ENABLED_CAPABILITIES 70
+#define WLAN_EID_MULTIPLE_BSSID 71
#define WLAN_EID_20_40_BSS_COEXISTENCE 72
#define WLAN_EID_20_40_BSS_INTOLERANT 73
#define WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS 74
+#define WLAN_EID_RIC_DESCRIPTOR 75
#define WLAN_EID_MMIE 76
+#define WLAN_EID_EVENT_REQUEST 78
+#define WLAN_EID_EVENT_REPORT 79
+#define WLAN_EID_DIAGNOSTIC_REQUEST 80
+#define WLAN_EID_DIAGNOSTIC_REPORT 81
+#define WLAN_EID_LOCATION_PARAMETERS 82
+#define WLAN_EID_NONTRANSMITTED_BSSID_CAPA 83
#define WLAN_EID_SSID_LIST 84
+#define WLAN_EID_MULTIPLE_BSSID_INDEX 85
+#define WLAN_EID_FMS_DESCRIPTOR 86
+#define WLAN_EID_FMS_REQUEST 87
+#define WLAN_EID_FMS_RESPONSE 88
+#define WLAN_EID_QOS_TRAFFIC_CAPABILITY 89
#define WLAN_EID_BSS_MAX_IDLE_PERIOD 90
#define WLAN_EID_TFS_REQ 91
#define WLAN_EID_TFS_RESP 92
#define WLAN_EID_WNMSLEEP 93
+#define WLAN_EID_TIM_BROADCAST_REQUEST 94
+#define WLAN_EID_TIM_BROADCAST_RESPONSE 95
+#define WLAN_EID_COLLOCATED_INTERFERENCE_REPORT 96
+#define WLAN_EID_CHANNEL_USAGE 97
#define WLAN_EID_TIME_ZONE 98
+#define WLAN_EID_DMS_REQUEST 99
+#define WLAN_EID_DMS_RESPONSE 100
#define WLAN_EID_LINK_ID 101
+#define WLAN_EID_WAKEUP_SCHEDULE 102
+#define WLAN_EID_CHANNEL_SWITCH_TIMING 104
+#define WLAN_EID_PTI_CONTROL 105
+#define WLAN_EID_TPU_BUFFER_STATUS 106
#define WLAN_EID_INTERWORKING 107
#define WLAN_EID_ADV_PROTO 108
+#define WLAN_EID_EXPEDITED_BANDWIDTH_REQ 109
#define WLAN_EID_QOS_MAP_SET 110
#define WLAN_EID_ROAMING_CONSORTIUM 111
+#define WLAN_EID_EMERGENCY_ALERT_ID 112
#define WLAN_EID_MESH_CONFIG 113
#define WLAN_EID_MESH_ID 114
+#define WLAN_EID_MESH_LINK_METRIC_REPORT 115
+#define WLAN_EID_CONGESTION_NOTIFICATION 116
#define WLAN_EID_PEER_MGMT 117
+#define WLAN_EID_MESH_CHANNEL_SWITCH_PARAMETERS 118
+#define WLAN_EID_MESH_AWAKE_WINDOW 119
+#define WLAN_EID_BEACON_TIMING 120
+#define WLAN_EID_MCCAOP_SETUP_REQUEST 121
+#define WLAN_EID_MCCAOP_SETUP_REPLY 122
+#define WLAN_EID_MCCAOP_ADVERTISEMENT 123
+#define WLAN_EID_MCCAOP_TEARDOWN 124
+#define WLAN_EID_GANN 125
+#define WLAN_EID_RANN 126
#define WLAN_EID_EXT_CAPAB 127
+#define WLAN_EID_PREQ 130
+#define WLAN_EID_PREP 131
+#define WLAN_EID_PERR 132
+#define WLAN_EID_PXU 137
+#define WLAN_EID_PXUC 138
#define WLAN_EID_AMPE 139
#define WLAN_EID_MIC 140
+#define WLAN_EID_DESTINATION_URI 141
+#define WLAN_EID_U_APSD_COEX 142
+#define WLAN_EID_DMG_WAKEUP_SCHEDULE 143
+#define WLAN_EID_EXTENDED_SCHEDULE 144
+#define WLAN_EID_STA_AVAILABILITY 145
+#define WLAN_EID_DMG_TSPEC 146
+#define WLAN_EID_NEXT_DMG_ATI 147
+#define WLAN_EID_DMG_CAPABILITIES 148
+#define WLAN_EID_DMG_OPERATION 151
+#define WLAN_EID_DMG_BSS_PARAMETER_CHANGE 152
+#define WLAN_EID_DMG_BEAM_REFINEMENT 153
+#define WLAN_EID_CHANNEL_MEASUREMENT_FEEDBACK 154
#define WLAN_EID_CCKM 156
+#define WLAN_EID_AWAKE_WINDOW 157
#define WLAN_EID_MULTI_BAND 158
+#define WLAN_EID_ADDBA_EXTENSION 159
+#define WLAN_EID_NEXTPCP_LIST 160
+#define WLAN_EID_PCP_HANDOVER 161
+#define WLAN_EID_DMG_LINK_MARGIN 162
+#define WLAN_EID_SWITCHING_STREAM 163
#define WLAN_EID_SESSION_TRANSITION 164
+#define WLAN_EID_DYNAMIC_TONE_PAIRING_REPORT 165
+#define WLAN_EID_CLUSTER_REPORT 166
+#define WLAN_EID_REPLAY_CAPABILITIES 167
+#define WLAN_EID_RELAY_TRANSFER_PARAM_SET 168
+#define WLAN_EID_BEAMLINK_MAINTENANCE 169
+#define WLAN_EID_MULTIPLE_MAC_SUBLAYERS 170
+#define WLAN_EID_U_PID 171
+#define WLAN_EID_DMG_LINK_ADAPTATION_ACK 172
+#define WLAN_EID_MCCAOP_ADVERTISEMENT_OVERVIEW 174
+#define WLAN_EID_QUIET_PERIOD_REQUEST 175
+#define WLAN_EID_QUIET_PERIOD_RESPONSE 177
+#define WLAN_EID_QMF_POLICY 181
+#define WLAN_EID_ECAPC_POLICY 182
+#define WLAN_EID_CLUSTER_TIME_OFFSET 183
+#define WLAN_EID_INTRA_ACCESS_CATEGORY_PRIORITY 184
+#define WLAN_EID_SCS_DESCRIPTOR 185
+#define WLAN_EID_QLOAD_REPORT 186
+#define WLAN_EID_HCCA_TXOP_UPDATE_COUNT 187
+#define WLAN_EID_HIGHER_LAYER_STREAM_ID 188
+#define WLAN_EID_GCR_GROUP_ADDRESS 189
+#define WLAN_EID_ANTENNA_SECTOR_ID_PATTERN 190
#define WLAN_EID_VHT_CAP 191
#define WLAN_EID_VHT_OPERATION 192
#define WLAN_EID_VHT_EXTENDED_BSS_LOAD 193
@@ -291,10 +434,124 @@
#define WLAN_EID_VHT_AID 197
#define WLAN_EID_VHT_QUIET_CHANNEL 198
#define WLAN_EID_VHT_OPERATING_MODE_NOTIFICATION 199
+#define WLAN_EID_UPSIM 200
+#define WLAN_EID_REDUCED_NEIGHBOR_REPORT 201
+#define WLAN_EID_TVHT_OPERATION 202
+#define WLAN_EID_DEVICE_LOCATION 204
+#define WLAN_EID_WHITE_SPACE_MAP 205
+#define WLAN_EID_FTM_PARAMETERS 206
#define WLAN_EID_VENDOR_SPECIFIC 221
-
-
-/* Action frame categories (IEEE 802.11-2007, 7.3.1.11, Table 7-24) */
+#define WLAN_EID_CAG_NUMBER 237
+#define WLAN_EID_AP_CSN 239
+#define WLAN_EID_FILS_INDICATION 240
+#define WLAN_EID_DILS 241
+#define WLAN_EID_FRAGMENT 242
+#define WLAN_EID_EXTENSION 255
+
+/* Element ID Extension (EID 255) values */
+#define WLAN_EID_EXT_ASSOC_DELAY_INFO 1
+#define WLAN_EID_EXT_FILS_REQ_PARAMS 2
+#define WLAN_EID_EXT_FILS_KEY_CONFIRM 3
+#define WLAN_EID_EXT_FILS_SESSION 4
+#define WLAN_EID_EXT_FILS_HLP_CONTAINER 5
+#define WLAN_EID_EXT_FILS_IP_ADDR_ASSIGN 6
+#define WLAN_EID_EXT_KEY_DELIVERY 7
+#define WLAN_EID_EXT_FILS_WRAPPED_DATA 8
+#define WLAN_EID_EXT_FTM_SYNC_INFO 9
+#define WLAN_EID_EXT_EXTENDED_REQUEST 10
+#define WLAN_EID_EXT_ESTIMATED_SERVICE_PARAMS 11
+#define WLAN_EID_EXT_FILS_PUBLIC_KEY 12
+#define WLAN_EID_EXT_FILS_NONCE 13
+#define WLAN_EID_EXT_FUTURE_CHANNEL_GUIDANCE 14
+#define WLAN_EID_EXT_OWE_DH_PARAM 32
+#define WLAN_EID_EXT_PASSWORD_IDENTIFIER 33
+#define WLAN_EID_EXT_HE_CAPABILITIES 35
+#define WLAN_EID_EXT_HE_OPERATION 36
+#define WLAN_EID_EXT_HE_MU_EDCA_PARAMS 38
+#define WLAN_EID_EXT_OCV_OCI 54
+
+/* Extended Capabilities field */
+#define WLAN_EXT_CAPAB_20_40_COEX 0
+#define WLAN_EXT_CAPAB_GLK 1
+#define WLAN_EXT_CAPAB_EXT_CHAN_SWITCH 2
+#define WLAN_EXT_CAPAB_GLK_GCR 3
+#define WLAN_EXT_CAPAB_PSMP 4
+/* 5 - Reserved */
+#define WLAN_EXT_CAPAB_S_PSMP 6
+#define WLAN_EXT_CAPAB_EVENT 7
+#define WLAN_EXT_CAPAB_DIAGNOSTICS 8
+#define WLAN_EXT_CAPAB_MULTICAST_DIAGNOSTICS 9
+#define WLAN_EXT_CAPAB_LOCATION_TRACKING 10
+#define WLAN_EXT_CAPAB_FMS 11
+#define WLAN_EXT_CAPAB_PROXY_ARP 12
+#define WLAN_EXT_CAPAB_COLL_INTERF_REP 13
+#define WLAN_EXT_CAPAB_CIVIC_LOCATION 14
+#define WLAN_EXT_CAPAB_GEOSPATIAL_LOCATION 15
+#define WLAN_EXT_CAPAB_TFS 16
+#define WLAN_EXT_CAPAB_WNM_SLEEP_MODE 17
+#define WLAN_EXT_CAPAB_TIM_BROADCAST 18
+#define WLAN_EXT_CAPAB_BSS_TRANSITION 19
+#define WLAN_EXT_CAPAB_QOS_TRAFFIC 20
+#define WLAN_EXT_CAPAB_AC_STA_COUNT 21
+#define WLAN_EXT_CAPAB_MULTIPLE_BSSID 22
+#define WLAN_EXT_CAPAB_TIMING_MEASUREMENT 23
+#define WLAN_EXT_CAPAB_CHANNEL_USAGE 24
+#define WLAN_EXT_CAPAB_SSID_LIST 25
+#define WLAN_EXT_CAPAB_DMS 26
+#define WLAN_EXT_CAPAB_UTF_TSF_OFFSET 27
+#define WLAN_EXT_CAPAB_TPU_BUFFER_STA 28
+#define WLAN_EXT_CAPAB_TDLS_PEER_PSM 29
+#define WLAN_EXT_CAPAB_TDLS_CHANNEL_SWITCH 30
+#define WLAN_EXT_CAPAB_INTERWORKING 31
+#define WLAN_EXT_CAPAB_QOS_MAP 32
+#define WLAN_EXT_CAPAB_EBR 33
+#define WLAN_EXT_CAPAB_SSPN_INTERFACE 34
+/* 35 - Reserved */
+#define WLAN_EXT_CAPAB_MSGCF 36
+#define WLAN_EXT_CAPAB_TDLS 37
+#define WLAN_EXT_CAPAB_TDLS_PROHIBITED 38
+#define WLAN_EXT_CAPAB_TDLS_CHANNEL_SWITCH_PROHIBITED 39
+#define WLAN_EXT_CAPAB_REJECT_UNADMITTED_FRAME 40
+#define WLAN_EXT_CAPAB_
+/* 41-43 - Service Interval Granularity */
+#define WLAN_EXT_CAPAB_IDENTIFIER_LOCATION 44
+#define WLAN_EXT_CAPAB_U_APSD_COEX 45
+#define WLAN_EXT_CAPAB_WNM_NOTIFCATION 46
+#define WLAN_EXT_CAPAB_QAB 47
+#define WLAN_EXT_CAPAB_UTF_8_SSID 48
+#define WLAN_EXT_CAPAB_QMF 49
+#define WLAN_EXT_CAPAB_QMF_RECONFIG 50
+#define WLAN_EXT_CAPAB_ROBUST_AV_STREAMING 51
+#define WLAN_EXT_CAPAB_ADVANCED_GCR 52
+#define WLAN_EXT_CAPAB_MESH_GCR 53
+#define WLAN_EXT_CAPAB_SCS 54
+#define WLAN_EXT_CAPAB_QLOAD_REPORT 55
+#define WLAN_EXT_CAPAB_ALT_EDCA 56
+#define WLAN_EXT_CAPAB_UNPROT_TXOP_NEG 57
+#define WLAN_EXT_CAPAB_PROT_TXOP_NEG 58
+/* 59 - Reserved */
+#define WLAN_EXT_CAPAB_PROT_QLOAD_REPORT 60
+#define WLAN_EXT_CAPAB_TDLS_WIDER_BW 61
+#define WLAN_EXT_CAPAB_OPMODE_NOTIF 62
+#define WLAN_EXT_CAPAB_
+/* 63-64 - Max Number of MSDUs In A-MSDU */
+#define WLAN_EXT_CAPAB_CHANNEL_SCHEDULE_MGMT 65
+#define WLAN_EXT_CAPAB_GEODB_INBAND_ENABLING_SIGNAL 66
+#define WLAN_EXT_CAPAB_NETWORK_CHANNEL_CTRL 67
+#define WLAN_EXT_CAPAB_WHITE_SPACE_MAP 68
+#define WLAN_EXT_CAPAB_CHANNEL_AVAIL_QUERY 69
+#define WLAN_EXT_CAPAB_FTM_RESPONDER 70
+#define WLAN_EXT_CAPAB_FTM_INITIATOR 71
+#define WLAN_EXT_CAPAB_FILS 72
+#define WLAN_EXT_CAPAB_EXT_SPECTRUM_MGMT 73
+#define WLAN_EXT_CAPAB_FUTURE_CHANNEL_GUIDANCE 74
+#define WLAN_EXT_CAPAB_PAD 75
+/* 76-79 - Reserved */
+#define WLAN_EXT_CAPAB_COMPLETE_NON_TX_BSSID_PROFILE 80
+#define WLAN_EXT_CAPAB_SAE_PW_ID 81
+#define WLAN_EXT_CAPAB_SAE_PW_ID_EXCLUSIVELY 82
+
+/* Action frame categories (IEEE Std 802.11-2016, 9.4.1.11, Table 9-76) */
#define WLAN_ACTION_SPECTRUM_MGMT 0
#define WLAN_ACTION_QOS 1
#define WLAN_ACTION_DLS 2
@@ -308,21 +565,59 @@
#define WLAN_ACTION_WNM 10
#define WLAN_ACTION_UNPROTECTED_WNM 11
#define WLAN_ACTION_TDLS 12
+#define WLAN_ACTION_MESH 13
+#define WLAN_ACTION_MULTIHOP 14
#define WLAN_ACTION_SELF_PROTECTED 15
+#define WLAN_ACTION_DMG 16
#define WLAN_ACTION_WMM 17 /* WMM Specification 1.1 */
#define WLAN_ACTION_FST 18
+#define WLAN_ACTION_ROBUST_AV_STREAMING 19
+#define WLAN_ACTION_UNPROTECTED_DMG 20
+#define WLAN_ACTION_VHT 21
+#define WLAN_ACTION_FILS 26
+#define WLAN_ACTION_VENDOR_SPECIFIC_PROTECTED 126
#define WLAN_ACTION_VENDOR_SPECIFIC 127
+/* Note: 128-255 used to report errors by setting category | 0x80 */
-/* Public action codes */
+/* Public action codes (IEEE Std 802.11-2016, 9.6.8.1, Table 9-307) */
#define WLAN_PA_20_40_BSS_COEX 0
+#define WLAN_PA_DSE_ENABLEMENT 1
+#define WLAN_PA_DSE_DEENABLEMENT 2
+#define WLAN_PA_DSE_REG_LOCATION_ANNOUNCE 3
+#define WLAN_PA_EXT_CHANNEL_SWITCH_ANNOUNCE 4
+#define WLAN_PA_DSE_MEASUREMENT_REQ 5
+#define WLAN_PA_DSE_MEASUREMENT_RESP 6
+#define WLAN_PA_MEASUREMENT_PILOT 7
+#define WLAN_PA_DSE_POWER_CONSTRAINT 8
#define WLAN_PA_VENDOR_SPECIFIC 9
#define WLAN_PA_GAS_INITIAL_REQ 10
#define WLAN_PA_GAS_INITIAL_RESP 11
#define WLAN_PA_GAS_COMEBACK_REQ 12
#define WLAN_PA_GAS_COMEBACK_RESP 13
#define WLAN_TDLS_DISCOVERY_RESPONSE 14
-
-/* Protected Dual of Public Action frames */
+#define WLAN_PA_LOCATION_TRACK_NOTIFICATION 15
+#define WLAN_PA_QAB_REQUEST_FRAME 16
+#define WLAN_PA_QAB_RESPONSE_FRAME 17
+#define WLAN_PA_QMF_POLICY 18
+#define WLAN_PA_QMF_POLICY_CHANGE 19
+#define WLAN_PA_QLOAD_REQUEST 20
+#define WLAN_PA_QLOAD_REPORT 21
+#define WLAN_PA_HCCA_TXOP_ADVERTISEMENT 22
+#define WLAN_PA_HCCA_TXOP_RESPONSE 23
+#define WLAN_PA_PUBLIC_KEY 24
+#define WLAN_PA_CHANNEL_AVAILABILITY_QUERY 25
+#define WLAN_PA_CHANNEL_SCHEDULE_MANAGEMENT 26
+#define WLAN_PA_CONTACT_VERIFICATION_SIGNAL 27
+#define WLAN_PA_GDD_ENABLEMENT_REQ 28
+#define WLAN_PA_GDD_ENABLEMENT_RESP 29
+#define WLAN_PA_NETWORK_CHANNEL_CONTROL 30
+#define WLAN_PA_WHITE_SPACE_MAP_ANNOUNCEMENT 31
+#define WLAN_PA_FTM_REQUEST 32
+#define WLAN_PA_FTM 33
+#define WLAN_PA_FILS_DISCOVERY 34
+
+/* Protected Dual of Public Action frames (IEEE Std 802.11-2016, 9.6.11,
+ * Table 9-332) */
#define WLAN_PROT_DSE_ENABLEMENT 1
#define WLAN_PROT_DSE_DEENABLEMENT 2
#define WLAN_PROT_EXT_CSA 4
@@ -334,6 +629,21 @@
#define WLAN_PROT_GAS_INITIAL_RESP 11
#define WLAN_PROT_GAS_COMEBACK_REQ 12
#define WLAN_PROT_GAS_COMEBACK_RESP 13
+#define WLAN_PROT_QAB_REQUEST_FRAME 16
+#define WLAN_PROT_QAB_RESPONSE_FRAME 17
+#define WLAN_PROT_QMF_POLICY 18
+#define WLAN_PROT_QMF_POLICY_CHANGE 19
+#define WLAN_PROT_QLOAD_REQUEST 20
+#define WLAN_PROT_QLOAD_REPORT 21
+#define WLAN_PROT_HCCA_TXOP_ADVERTISEMENT 22
+#define WLAN_PROT_HCCA_TXOP_RESPONSE 23
+#define WLAN_PROT_CHANNEL_AVAILABILITY_QUERY 25
+#define WLAN_PROT_CHANNEL_SCHEDULE_MANAGEMENT 26
+#define WLAN_PROT_CONTACT_VERIFICATION_SIGNAL 27
+#define WLAN_PROT_GDD_ENABLEMENT_REQ 28
+#define WLAN_PROT_GDD_ENABLEMENT_RESP 29
+#define WLAN_PROT_NETWORK_CHANNEL_CONTROL 30
+#define WLAN_PROT_WHITE_SPACE_MAP_ANNOUNCEMENT 31
/* SA Query Action frame (IEEE 802.11w/D8.0, 7.4.9) */
#define WLAN_SA_QUERY_REQUEST 0
@@ -362,10 +672,14 @@
#define WLAN_RRM_NEIGHBOR_REPORT_REQUEST 4
#define WLAN_RRM_NEIGHBOR_REPORT_RESPONSE 5
-/* Radio Measurement capabilities (from RRM Capabilities IE) */
+/* Radio Measurement capabilities (from RM Enabled Capabilities element)
+ * IEEE Std 802.11-2016, 9.4.2.45, Table 9-157 */
/* byte 1 (out of 5) */
#define WLAN_RRM_CAPS_LINK_MEASUREMENT BIT(0)
#define WLAN_RRM_CAPS_NEIGHBOR_REPORT BIT(1)
+#define WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE BIT(4)
+#define WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE BIT(5)
+#define WLAN_RRM_CAPS_BEACON_REPORT_TABLE BIT(6)
/* byte 2 (out of 5) */
#define WLAN_RRM_CAPS_LCI_MEASUREMENT BIT(4)
/* byte 5 (out of 5) */
@@ -398,16 +712,18 @@
#define INTERWORKING_ANT_TEST 6
#define INTERWORKING_ANT_WILDCARD 15
-/* Advertisement Protocol ID definitions (IEEE Std 802.11u-2011) */
+/* Advertisement Protocol ID definitions (IEEE Std 802.11-2016, Table 9-215) */
enum adv_proto_id {
ACCESS_NETWORK_QUERY_PROTOCOL = 0,
MIH_INFO_SERVICE = 1,
MIH_CMD_AND_EVENT_DISCOVERY = 2,
EMERGENCY_ALERT_SYSTEM = 3,
+ REGISTERED_LOCATION_QUERY_PROTO = 4,
ADV_PROTO_VENDOR_SPECIFIC = 221
};
-/* Access Network Query Protocol info ID definitions (IEEE Std 802.11u-2011) */
+/* Access Network Query Protocol info ID definitions (IEEE Std 802.11-2016,
+ * Table 9-271; P802.11ai) */
enum anqp_info_id {
ANQP_QUERY_LIST = 256,
ANQP_CAPABILITY_LIST = 257,
@@ -426,9 +742,14 @@ enum anqp_info_id {
ANQP_TDLS_CAPABILITY = 270,
ANQP_EMERGENCY_NAI = 271,
ANQP_NEIGHBOR_REPORT = 272,
+ ANQP_QUERY_AP_LIST = 273,
+ ANQP_AP_LIST_RESPONSE = 274,
+ ANQP_FILS_REALM_INFO = 275,
+ ANQP_CAG = 276,
ANQP_VENUE_URL = 277,
ANQP_ADVICE_OF_CHARGE = 278,
ANQP_LOCAL_CONTENT = 279,
+ ANQP_NETWORK_AUTH_TYPE_TIMESTAMP = 280,
ANQP_VENDOR_SPECIFIC = 56797
};
@@ -505,6 +826,11 @@ enum lci_req_subelem {
LCI_REQ_SUBELEM_MAX_AGE = 4,
};
+#define FILS_NONCE_LEN 16
+#define FILS_SESSION_LEN 8
+#define FILS_CACHE_ID_LEN 2
+#define FILS_MAX_KEY_AUTH_LEN 48
+
#ifdef _MSC_VER
#pragma pack(push, 1)
#endif /* _MSC_VER */
@@ -621,10 +947,12 @@ struct ieee80211_mgmt {
struct {
u8 action;
u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
+ u8 variable[]; /* OCI element */
} STRUCT_PACKED sa_query_req;
struct {
u8 action; /* */
u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
+ u8 variable[]; /* OCI element */
} STRUCT_PACKED sa_query_resp;
struct {
u8 action;
@@ -678,6 +1006,16 @@ struct ieee80211_mgmt {
u8 variable[];
} STRUCT_PACKED bss_tm_query;
struct {
+ u8 action; /* 11 */
+ u8 dialog_token;
+ u8 req_info;
+ } STRUCT_PACKED coloc_intf_req;
+ struct {
+ u8 action; /* 12 */
+ u8 dialog_token;
+ u8 variable[];
+ } STRUCT_PACKED coloc_intf_report;
+ struct {
u8 action; /* 15 */
u8 variable[];
} STRUCT_PACKED slf_prot_action;
@@ -887,6 +1225,7 @@ struct ieee80211_ampe_ie {
#define VHT_CAP_SUPP_CHAN_WIDTH_160MHZ ((u32) BIT(2))
#define VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ ((u32) BIT(3))
#define VHT_CAP_SUPP_CHAN_WIDTH_MASK ((u32) BIT(2) | BIT(3))
+#define VHT_CAP_SUPP_CHAN_WIDTH_MASK_SHIFT 2
#define VHT_CAP_RXLDPC ((u32) BIT(4))
#define VHT_CAP_SHORT_GI_80 ((u32) BIT(5))
#define VHT_CAP_SHORT_GI_160 ((u32) BIT(6))
@@ -953,6 +1292,15 @@ struct ieee80211_ampe_ie {
#define OSEN_IE_VENDOR_TYPE 0x506f9a12
#define MBO_IE_VENDOR_TYPE 0x506f9a16
#define MBO_OUI_TYPE 22
+#define OWE_IE_VENDOR_TYPE 0x506f9a1c
+#define OWE_OUI_TYPE 28
+#define MULTI_AP_OUI_TYPE 0x1B
+
+#define MULTI_AP_SUB_ELEM_TYPE 0x06
+#define MULTI_AP_TEAR_DOWN BIT(4)
+#define MULTI_AP_FRONTHAUL_BSS BIT(5)
+#define MULTI_AP_BACKHAUL_BSS BIT(6)
+#define MULTI_AP_BACKHAUL_STA BIT(7)
#define WMM_OUI_TYPE 2
#define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0
@@ -1072,6 +1420,7 @@ enum wmm_ac {
#define HS20_INDICATION_OUI_TYPE 16
#define HS20_ANQP_OUI_TYPE 17
#define HS20_OSEN_OUI_TYPE 18
+#define HS20_ROAMING_CONS_SEL_OUI_TYPE 29
#define HS20_STYPE_QUERY_LIST 1
#define HS20_STYPE_CAPABILITY_LIST 2
#define HS20_STYPE_OPERATOR_FRIENDLY_NAME 3
@@ -1082,21 +1431,29 @@ enum wmm_ac {
#define HS20_STYPE_OSU_PROVIDERS_LIST 8
#define HS20_STYPE_ICON_REQUEST 10
#define HS20_STYPE_ICON_BINARY_FILE 11
+#define HS20_STYPE_OPERATOR_ICON_METADATA 12
+#define HS20_STYPE_OSU_PROVIDERS_NAI_LIST 13
#define HS20_DGAF_DISABLED 0x01
#define HS20_PPS_MO_ID_PRESENT 0x02
#define HS20_ANQP_DOMAIN_ID_PRESENT 0x04
-#define HS20_VERSION 0x10 /* Release 2 */
+#ifndef HS20_VERSION
+#define HS20_VERSION 0x20 /* Release 3 */
+#endif /* HS20_VERSION */
/* WNM-Notification WFA vendors specific subtypes */
#define HS20_WNM_SUB_REM_NEEDED 0
#define HS20_WNM_DEAUTH_IMMINENT_NOTICE 1
+#define WFA_WNM_NOTIF_SUBELEM_NON_PREF_CHAN_REPORT 2
+#define WFA_WNM_NOTIF_SUBELEM_CELL_DATA_CAPA 3
+#define HS20_WNM_T_C_ACCEPTANCE 4
#define HS20_DEAUTH_REASON_CODE_BSS 0
#define HS20_DEAUTH_REASON_CODE_ESS 1
/* MBO v0.0_r19, 4.2: MBO Attributes */
/* Table 4-5: MBO Attributes */
+/* OCE v0.0.10, Table 4-3: OCE Attributes */
enum mbo_attr_id {
MBO_ATTR_ID_AP_CAPA_IND = 1,
MBO_ATTR_ID_NON_PREF_CHAN_REPORT = 2,
@@ -1106,6 +1463,10 @@ enum mbo_attr_id {
MBO_ATTR_ID_TRANSITION_REASON = 6,
MBO_ATTR_ID_TRANSITION_REJECT_REASON = 7,
MBO_ATTR_ID_ASSOC_RETRY_DELAY = 8,
+ OCE_ATTR_ID_CAPA_IND = 101,
+ OCE_ATTR_ID_RSSI_BASED_ASSOC_REJECT = 102,
+ OCE_ATTR_ID_REDUCED_WAN_METRICS = 103,
+ OCE_ATTR_ID_RNR_COMPLETENESS = 104,
};
/* MBO v0.0_r19, 4.2.1: MBO AP Capability Indication Attribute */
@@ -1174,15 +1535,17 @@ enum mbo_transition_reject_reason {
MBO_TRANSITION_REJECT_REASON_SERVICES = 6,
};
-/* MBO v0.0_r19, 4.4: WNM-Notification vendor subelements */
-enum wfa_wnm_notif_subelem_id {
- WFA_WNM_NOTIF_SUBELEM_NON_PREF_CHAN_REPORT = 2,
- WFA_WNM_NOTIF_SUBELEM_CELL_DATA_CAPA = 3,
-};
-
-/* MBO v0.0_r25, 4.3: MBO ANQP-elements */
+/* MBO v0.0_r27, 4.3: MBO ANQP-elements */
#define MBO_ANQP_OUI_TYPE 0x12
-#define MBO_ANQP_SUBTYPE_CELL_CONN_PREF 1
+#define MBO_ANQP_SUBTYPE_QUERY_LIST 1
+#define MBO_ANQP_SUBTYPE_CELL_CONN_PREF 2
+#define MAX_MBO_ANQP_SUBTYPE MBO_ANQP_SUBTYPE_CELL_CONN_PREF
+
+/* OCE v0.0.10, 4.2.1: OCE Capability Indication Attribute */
+#define OCE_RELEASE 1
+#define OCE_RELEASE_MASK (BIT(0) | BIT(1) | BIT(2))
+#define OCE_IS_STA_CFON BIT(3)
+#define OCE_IS_NON_OCE_AP_PRESENT BIT(4)
/* Wi-Fi Direct (P2P) */
@@ -1331,7 +1694,9 @@ enum wifi_display_subelem {
WFD_SUBELEM_COUPLED_SINK = 6,
WFD_SUBELEM_EXT_CAPAB = 7,
WFD_SUBELEM_LOCAL_IP_ADDRESS = 8,
- WFD_SUBELEM_SESSION_INFO = 9
+ WFD_SUBELEM_SESSION_INFO = 9,
+ WFD_SUBELEM_MAC_INFO = 10,
+ WFD_SUBELEM_R2_DEVICE_INFO = 11,
};
/* 802.11s */
@@ -1363,41 +1728,6 @@ enum plink_action_field {
#define VENDOR_HT_CAPAB_OUI_TYPE 0x33 /* 00-90-4c:0x33 */
-/* cipher suite selectors */
-#define WLAN_CIPHER_SUITE_USE_GROUP 0x000FAC00
-#define WLAN_CIPHER_SUITE_WEP40 0x000FAC01
-#define WLAN_CIPHER_SUITE_TKIP 0x000FAC02
-/* reserved: 0x000FAC03 */
-#define WLAN_CIPHER_SUITE_CCMP 0x000FAC04
-#define WLAN_CIPHER_SUITE_WEP104 0x000FAC05
-#define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06
-#define WLAN_CIPHER_SUITE_NO_GROUP_ADDR 0x000FAC07
-#define WLAN_CIPHER_SUITE_GCMP 0x000FAC08
-#define WLAN_CIPHER_SUITE_GCMP_256 0x000FAC09
-#define WLAN_CIPHER_SUITE_CCMP_256 0x000FAC0A
-#define WLAN_CIPHER_SUITE_BIP_GMAC_128 0x000FAC0B
-#define WLAN_CIPHER_SUITE_BIP_GMAC_256 0x000FAC0C
-#define WLAN_CIPHER_SUITE_BIP_CMAC_256 0x000FAC0D
-
-#define WLAN_CIPHER_SUITE_SMS4 0x00147201
-
-#define WLAN_CIPHER_SUITE_CKIP 0x00409600
-#define WLAN_CIPHER_SUITE_CKIP_CMIC 0x00409601
-#define WLAN_CIPHER_SUITE_CMIC 0x00409602
-#define WLAN_CIPHER_SUITE_KRK 0x004096FF /* for nl80211 use only */
-
-/* AKM suite selectors */
-#define WLAN_AKM_SUITE_8021X 0x000FAC01
-#define WLAN_AKM_SUITE_PSK 0x000FAC02
-#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
-#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
-#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
-#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
-#define WLAN_AKM_SUITE_8021X_SUITE_B 0x000FAC11
-#define WLAN_AKM_SUITE_8021X_SUITE_B_192 0x000FAC12
-#define WLAN_AKM_SUITE_CCKM 0x00409600
-#define WLAN_AKM_SUITE_OSEN 0x506f9a01
-
/* IEEE 802.11v - WNM Action field values */
enum wnm_action {
@@ -1559,6 +1889,117 @@ struct rrm_link_measurement_report {
u8 variable[0];
} STRUCT_PACKED;
+/* IEEE Std 802.11-2016, 9.4.2.21 - Measurement Request element */
+struct rrm_measurement_request_element {
+ u8 eid; /* Element ID */
+ u8 len; /* Length */
+ u8 token; /* Measurement Token */
+ u8 mode; /* Measurement Request Mode */
+ u8 type; /* Measurement Type */
+ u8 variable[0]; /* Measurement Request */
+} STRUCT_PACKED;
+
+/* IEEE Std 802.11-2016, Figure 9-148 - Measurement Request Mode field */
+#define MEASUREMENT_REQUEST_MODE_PARALLEL BIT(0)
+#define MEASUREMENT_REQUEST_MODE_ENABLE BIT(1)
+#define MEASUREMENT_REQUEST_MODE_REQUEST BIT(2)
+#define MEASUREMENT_REQUEST_MODE_REPORT BIT(3)
+#define MEASUREMENT_REQUEST_MODE_DURATION_MANDATORY BIT(4)
+
+/* IEEE Std 802.11-2016, 9.4.2.21.7 - Beacon request */
+struct rrm_measurement_beacon_request {
+ u8 oper_class; /* Operating Class */
+ u8 channel; /* Channel Number */
+ le16 rand_interval; /* Randomization Interval (in TUs) */
+ le16 duration; /* Measurement Duration (in TUs) */
+ u8 mode; /* Measurement Mode */
+ u8 bssid[ETH_ALEN]; /* BSSID */
+ u8 variable[0]; /* Optional Subelements */
+} STRUCT_PACKED;
+
+/*
+ * IEEE Std 802.11-2016, Table 9-87 - Measurement Mode definitions for Beacon
+ * request
+ */
+enum beacon_report_mode {
+ BEACON_REPORT_MODE_PASSIVE = 0,
+ BEACON_REPORT_MODE_ACTIVE = 1,
+ BEACON_REPORT_MODE_TABLE = 2,
+};
+
+/* IEEE Std 802.11-2016, Table 9-88 - Beacon Request subelement IDs */
+/* IEEE P802.11-REVmd/D2.0, Table 9-106 - Optional subelement IDs for
+ * Beacon request */
+#define WLAN_BEACON_REQUEST_SUBELEM_SSID 0
+#define WLAN_BEACON_REQUEST_SUBELEM_INFO 1 /* Beacon Reporting */
+#define WLAN_BEACON_REQUEST_SUBELEM_DETAIL 2 /* Reporting Detail */
+#define WLAN_BEACON_REQUEST_SUBELEM_REQUEST 10
+#define WLAN_BEACON_REQUEST_SUBELEM_AP_CHANNEL 51 /* AP Channel Report */
+#define WLAN_BEACON_REQUEST_SUBELEM_LAST_INDICATION 164
+#define WLAN_BEACON_REQUEST_SUBELEM_VENDOR 221
+
+/*
+ * IEEE Std 802.11-2016, Table 9-90 - Reporting Detail values
+ */
+enum beacon_report_detail {
+ /* No fixed-length fields or elements */
+ BEACON_REPORT_DETAIL_NONE = 0,
+ /* All fixed-length fields and any requested elements in the Request
+ * element if present */
+ BEACON_REPORT_DETAIL_REQUESTED_ONLY = 1,
+ /* All fixed-length fields and elements (default, used when Reporting
+ * Detail subelement is not included in a Beacon request) */
+ BEACON_REPORT_DETAIL_ALL_FIELDS_AND_ELEMENTS = 2,
+};
+
+/* IEEE Std 802.11-2016, 9.4.2.22 - Measurement Report element */
+struct rrm_measurement_report_element {
+ u8 eid; /* Element ID */
+ u8 len; /* Length */
+ u8 token; /* Measurement Token */
+ u8 mode; /* Measurement Report Mode */
+ u8 type; /* Measurement Type */
+ u8 variable[0]; /* Measurement Report */
+} STRUCT_PACKED;
+
+/* IEEE Std 802.11-2016, Figure 9-192 - Measurement Report Mode field */
+#define MEASUREMENT_REPORT_MODE_ACCEPT 0
+#define MEASUREMENT_REPORT_MODE_REJECT_LATE BIT(0)
+#define MEASUREMENT_REPORT_MODE_REJECT_INCAPABLE BIT(1)
+#define MEASUREMENT_REPORT_MODE_REJECT_REFUSED BIT(2)
+
+/* IEEE Std 802.11-2016, 9.4.2.22.7 - Beacon report */
+struct rrm_measurement_beacon_report {
+ u8 op_class; /* Operating Class */
+ u8 channel; /* Channel Number */
+ le64 start_time; /* Actual Measurement Start Time
+ * (in TSF of the BSS requesting the measurement) */
+ le16 duration; /* in TUs */
+ u8 report_info; /* Reported Frame Information */
+ u8 rcpi; /* RCPI */
+ u8 rsni; /* RSNI */
+ u8 bssid[ETH_ALEN]; /* BSSID */
+ u8 antenna_id; /* Antenna ID */
+ le32 parent_tsf; /* Parent TSF */
+ u8 variable[0]; /* Optional Subelements */
+} STRUCT_PACKED;
+
+/* IEEE Std 802.11-2016, Table 9-112 - Beacon report Subelement IDs */
+/* IEEE P802.11-REVmd/D2.0, Table 9-130 - Optional subelement IDs for
+ * Beacon report */
+#define WLAN_BEACON_REPORT_SUBELEM_FRAME_BODY 1
+#define WLAN_BEACON_REPORT_SUBELEM_FRAME_BODY_FRAGMENT_ID 2
+#define WLAN_BEACON_REPORT_SUBELEM_LAST_INDICATION 164
+#define WLAN_BEACON_REPORT_SUBELEM_VENDOR 221
+
+/* IEEE P802.11-REVmd/D2.0, Table 9-232 - Data field format of the
+ * Reported Frame Body Fragment ID subelement */
+#define REPORTED_FRAME_BODY_SUBELEM_LEN 4
+#define REPORTED_FRAME_BODY_MORE_FRAGMENTS BIT(7)
+
+/* IEEE P802.11-REVmd/D2.0, 9.4.2.21.7 - Beacon report */
+#define BEACON_REPORT_LAST_INDICATION_SUBELEM_LEN 3
+
/* IEEE Std 802.11ad-2012 - Multi-band element */
struct multi_band_ie {
u8 eid; /* WLAN_EID_MULTI_BAND */
@@ -1660,4 +2101,83 @@ enum nr_chan_width {
NR_CHAN_WIDTH_80P80 = 4,
};
+struct ieee80211_he_capabilities {
+ u8 he_mac_capab_info[6];
+ u8 he_phy_capab_info[11];
+ u8 he_txrx_mcs_support[12]; /* TODO: 4, 8, or 12 octets */
+ /* PPE Thresholds (optional) */
+} STRUCT_PACKED;
+
+struct ieee80211_he_operation {
+ u32 he_oper_params; /* HE Operation Parameters[3] and
+ * BSS Color Information[1] */
+ u8 he_mcs_nss_set[2];
+ u8 vht_op_info_chwidth;
+ u8 vht_op_info_chan_center_freq_seg0_idx;
+ u8 vht_op_info_chan_center_freq_seg1_idx;
+ /* Followed by conditional MaxBSSID Indicator subfield (u8) */
+} STRUCT_PACKED;
+
+/* HE Capabilities Information defines */
+#define HE_PHYCAP_SU_BEAMFORMER_CAPAB_IDX 3
+#define HE_PHYCAP_SU_BEAMFORMER_CAPAB ((u8) BIT(7))
+#define HE_PHYCAP_SU_BEAMFORMEE_CAPAB_IDX 4
+#define HE_PHYCAP_SU_BEAMFORMEE_CAPAB ((u8) BIT(0))
+#define HE_PHYCAP_MU_BEAMFORMER_CAPAB_IDX 4
+#define HE_PHYCAP_MU_BEAMFORMER_CAPAB ((u8) BIT(1))
+
+/* HE Operation defines */
+/* HE Operation Parameters and BSS Color Information fields */
+#define HE_OPERATION_BSS_COLOR_MASK ((u32) (BIT(0) | BIT(1) | \
+ BIT(2) | BIT(3) | \
+ BIT(4) | BIT(5)))
+#define HE_OPERATION_PARTIAL_BSS_COLOR ((u32) BIT(6))
+#define HE_OPERATION_BSS_COLOR_DISABLED ((u32) BIT(7))
+#define HE_OPERATION_DFLT_PE_DURATION_MASK ((u32) (BIT(8) | BIT(9) | \
+ BIT(10)))
+#define HE_OPERATION_DFLT_PE_DURATION_OFFSET 8
+#define HE_OPERATION_TWT_REQUIRED ((u32) BIT(11))
+#define HE_OPERATION_RTS_THRESHOLD_MASK ((u32) (BIT(12) | BIT(13) | \
+ BIT(14) | BIT(15) | \
+ BIT(16) | BIT(17) | \
+ BIT(18) | BIT(19) | \
+ BIT(20) | BIT(21)))
+#define HE_OPERATION_RTS_THRESHOLD_OFFSET 12
+
+struct ieee80211_he_mu_edca_parameter_set {
+ u8 he_qos_info;
+ u8 he_mu_ac_be_param[3];
+ u8 he_mu_ac_bk_param[3];
+ u8 he_mu_ac_vi_param[3];
+ u8 he_mu_ac_vo_param[3];
+} STRUCT_PACKED;
+
+/* HE MU AC parameter record field format */
+/* ACI/AIFSN */
+#define HE_MU_AC_PARAM_ACI_IDX 0
+#define HE_MU_AC_PARAM_AIFSN ((u8) (BIT(0) | BIT(1) | BIT(2) | BIT(3)))
+#define HE_MU_AC_PARAM_ACM ((u8) BIT(4))
+#define HE_MU_AC_PARAM_ACI ((u8) (BIT(5) | BIT(6)))
+/* B7: Reserved */
+
+/* ECWmin/ECWmax */
+#define HE_MU_AC_PARAM_ECW_IDX 1
+#define HE_MU_AC_PARAM_ECWMIN ((u8) (BIT(0) | BIT(1) | BIT(2) | BIT(3)))
+#define HE_MU_AC_PARAM_ECWMAX ((u8) (BIT(4) | BIT(5) | BIT(6) | BIT(7)))
+
+/* MU EDCA Timer */
+#define HE_MU_AC_PARAM_TIMER_IDX 2
+
+/* HE QoS Info field */
+#define HE_QOS_INFO_EDCA_PARAM_SET_COUNT ((u8) (BIT(0) | BIT(1) | \
+ BIT(2) | BIT(3)))
+#define HE_QOS_INFO_Q_ACK ((u8) (BIT(4)))
+#define HE_QOS_INFO_QUEUE_REQUEST ((u8) (BIT(5)))
+#define HE_QOS_INFO_TXOP_REQUEST ((u8) (BIT(6)))
+/* B7: Reserved if sent by an AP; More Data Ack if sent by a non-AP STA */
+#define HE_QOS_INFO_MORE_DATA_ACK ((u8) (BIT(7)))
+
+/* DPP Public Action frame identifiers - OUI_WFA */
+#define DPP_OUI_TYPE 0x1A
+
#endif /* IEEE802_11_DEFS_H */
diff --git a/freebsd/contrib/wpa/src/common/ieee802_1x_defs.h b/freebsd/contrib/wpa/src/common/ieee802_1x_defs.h
new file mode 100644
index 00000000..e7acff10
--- /dev/null
+++ b/freebsd/contrib/wpa/src/common/ieee802_1x_defs.h
@@ -0,0 +1,86 @@
+/*
+ * IEEE Std 802.1X-2010 definitions
+ * Copyright (c) 2013-2014, Qualcomm Atheros, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef IEEE802_1X_DEFS_H
+#define IEEE802_1X_DEFS_H
+
+#define CS_ID_LEN 8
+#define CS_ID_GCM_AES_128 0x0080020001000001ULL
+#define CS_NAME_GCM_AES_128 "GCM-AES-128"
+#define CS_ID_GCM_AES_256 0x0080c20001000002ULL
+#define CS_NAME_GCM_AES_256 "GCM-AES-256"
+
+enum macsec_policy {
+ /**
+ * Should secure sessions.
+ * This accepts key server's advice to determine whether to secure the
+ * session or not.
+ */
+ SHOULD_SECURE,
+
+ /**
+ * Disabled MACsec - do not secure sessions.
+ */
+ DO_NOT_SECURE,
+
+ /**
+ * Should secure sessions, and try to use encryption.
+ * Like @SHOULD_SECURE, this follows the key server's decision.
+ */
+ SHOULD_ENCRYPT,
+};
+
+
+/* IEEE Std 802.1X-2010 - Table 11-6 - MACsec Capability */
+enum macsec_cap {
+ /**
+ * MACsec is not implemented
+ */
+ MACSEC_CAP_NOT_IMPLEMENTED,
+
+ /**
+ * 'Integrity without confidentiality'
+ */
+ MACSEC_CAP_INTEGRITY,
+
+ /**
+ * 'Integrity without confidentiality' and
+ * 'Integrity and confidentiality' with a confidentiality offset of 0
+ */
+ MACSEC_CAP_INTEG_AND_CONF,
+
+ /**
+ * 'Integrity without confidentiality' and
+ * 'Integrity and confidentiality' with a confidentiality offset of 0,
+ * 30, 50
+ */
+ MACSEC_CAP_INTEG_AND_CONF_0_30_50,
+};
+
+enum validate_frames {
+ Disabled,
+ Checked,
+ Strict,
+};
+
+/* IEEE Std 802.1X-2010 - Table 11-6 - Confidentiality Offset */
+enum confidentiality_offset {
+ CONFIDENTIALITY_NONE = 0,
+ CONFIDENTIALITY_OFFSET_0 = 1,
+ CONFIDENTIALITY_OFFSET_30 = 2,
+ CONFIDENTIALITY_OFFSET_50 = 3,
+};
+
+/* IEEE Std 802.1X-2010 - Table 9-2 */
+#define DEFAULT_PRIO_INFRA_PORT 0x10
+#define DEFAULT_PRIO_PRIMRAY_AP 0x30
+#define DEFAULT_PRIO_SECONDARY_AP 0x50
+#define DEFAULT_PRIO_GROUP_CA_MEMBER 0x70
+#define DEFAULT_PRIO_NOT_KEY_SERVER 0xFF
+
+#endif /* IEEE802_1X_DEFS_H */
diff --git a/freebsd/contrib/wpa/src/common/ocv.h b/freebsd/contrib/wpa/src/common/ocv.h
new file mode 100644
index 00000000..6379d9d0
--- /dev/null
+++ b/freebsd/contrib/wpa/src/common/ocv.h
@@ -0,0 +1,40 @@
+/*
+ * Operating Channel Validation (OCV)
+ * Copyright (c) 2018, Mathy Vanhoef
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef OCV_H
+#define OCV_H
+
+struct wpa_channel_info;
+
+struct oci_info {
+ /* Values in the OCI element */
+ u8 op_class;
+ u8 channel;
+ u8 seg1_idx;
+
+ /* Derived values for easier verification */
+ int freq;
+ int sec_channel;
+ int chanwidth;
+};
+
+#define OCV_OCI_LEN 3
+#define OCV_OCI_EXTENDED_LEN (3 + OCV_OCI_LEN)
+#define OCV_OCI_KDE_LEN (2 + RSN_SELECTOR_LEN + OCV_OCI_LEN)
+
+extern char ocv_errorstr[256];
+
+int ocv_derive_all_parameters(struct oci_info *oci);
+int ocv_insert_oci(struct wpa_channel_info *ci, u8 **argpos);
+int ocv_insert_oci_kde(struct wpa_channel_info *ci, u8 **argpos);
+int ocv_insert_extended_oci(struct wpa_channel_info *ci, u8 *pos);
+int ocv_verify_tx_params(const u8 *oci_ie, size_t oci_ie_len,
+ struct wpa_channel_info *ci, int tx_chanwidth,
+ int tx_seg1_idx);
+
+#endif /* OCV_H */
diff --git a/freebsd/contrib/wpa/src/common/qca-vendor.h b/freebsd/contrib/wpa/src/common/qca-vendor.h
index adaec890..c34a3bc1 100644
--- a/freebsd/contrib/wpa/src/common/qca-vendor.h
+++ b/freebsd/contrib/wpa/src/common/qca-vendor.h
@@ -1,6 +1,7 @@
/*
* Qualcomm Atheros OUI and vendor specific assignments
- * Copyright (c) 2014-2015, Qualcomm Atheros, Inc.
+ * Copyright (c) 2014-2017, Qualcomm Atheros, Inc.
+ * Copyright (c) 2018, The Linux Foundation
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -41,15 +42,22 @@ enum qca_radiotap_vendor_ids {
*
* @QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY: Recommendation of frequency
* ranges to avoid to reduce issues due to interference or internal
- * co-existence information in the driver. The event data structure is
- * defined in struct qca_avoid_freq_list.
+ * co-existence information in the driver. These frequencies aim to
+ * minimize the traffic but not to totally avoid the traffic. That said
+ * for a P2P use case, these frequencies are allowed for the P2P
+ * discovery/negotiation but avoid the group to get formed on these
+ * frequencies. The event data structure is defined in
+ * struct qca_avoid_freq_list.
*
* @QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY: Command to check driver support
* for DFS offloading.
*
* @QCA_NL80211_VENDOR_SUBCMD_NAN: NAN command/event which is used to pass
* NAN Request/Response and NAN Indication messages. These messages are
- * interpreted between the framework and the firmware component.
+ * interpreted between the framework and the firmware component. While
+ * sending the command from userspace to the driver, payload is not
+ * encapsulated inside any attribute. Attribute QCA_WLAN_VENDOR_ATTR_NAN
+ * is used when receiving vendor events in userspace from the driver.
*
* @QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY: Set key operation that can be
* used to configure PMK to the driver even when not connected. This can
@@ -90,6 +98,75 @@ enum qca_radiotap_vendor_ids {
* which supports DFS offloading, to indicate a radar pattern has been
* detected. The channel is now unusable.
*
+ * @QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET: Get the feature bitmap
+ * based on enum wifi_logger_supported_features. Attributes defined in
+ * enum qca_wlan_vendor_attr_get_logger_features.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA: Get the ring data from a particular
+ * logger ring, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID is passed as the
+ * attribute for this command. Attributes defined in
+ * enum qca_wlan_vendor_attr_wifi_logger_start.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES: Get the supported TDLS
+ * capabilities of the driver, parameters includes the attributes defined
+ * in enum qca_wlan_vendor_attr_tdls_get_capabilities.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS: Vendor command used to offload
+ * sending of certain periodic IP packet to firmware, attributes defined in
+ * enum qca_wlan_vendor_attr_offloaded_packets.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI: Command used to configure RSSI
+ * monitoring, defines min and max RSSI which are configured for RSSI
+ * monitoring. Also used to notify the RSSI breach and provides the BSSID
+ * and RSSI value that was breached. Attributes defined in
+ * enum qca_wlan_vendor_attr_rssi_monitoring.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_NDP: Command used for performing various NAN
+ * Data Path (NDP) related operations, attributes defined in
+ * enum qca_wlan_vendor_attr_ndp_params.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD: Command used to enable/disable
+ * Neighbour Discovery offload, attributes defined in
+ * enum qca_wlan_vendor_attr_nd_offload.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER: Used to set/get the various
+ * configuration parameter for BPF packet filter, attributes defined in
+ * enum qca_wlan_vendor_attr_packet_filter.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE: Gets the driver-firmware
+ * maximum supported size, attributes defined in
+ * enum qca_wlan_vendor_drv_info.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS: Command to get various
+ * data about wake reasons and datapath IP statistics, attributes defined
+ * in enum qca_wlan_vendor_attr_wake_stats.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG: Command used to set configuration
+ * for IEEE 802.11 communicating outside the context of a basic service
+ * set, called OCB command. Uses the attributes defines in
+ * enum qca_wlan_vendor_attr_ocb_set_config.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME: Command used to set OCB
+ * UTC time. Use the attributes defines in
+ * enum qca_wlan_vendor_attr_ocb_set_utc_time.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT: Command used to start
+ * sending OCB timing advert frames. Uses the attributes defines in
+ * enum qca_wlan_vendor_attr_ocb_start_timing_advert.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT: Command used to stop
+ * OCB timing advert. Uses the attributes defines in
+ * enum qca_wlan_vendor_attr_ocb_stop_timing_advert.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER: Command used to get TSF
+ * timer value. Uses the attributes defines in
+ * enum qca_wlan_vendor_attr_ocb_get_tsf_resp.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES: Command/event to update the
+ * link properties of the respective interface. As an event, is used
+ * to notify the connected station's status. The attributes for this
+ * command are defined in enum qca_wlan_vendor_attr_link_properties.
+ *
* @QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START: Command used to
* start the P2P Listen offload function in device and pass the listen
* channel, period, interval, count, device types, and vendor specific
@@ -164,8 +241,11 @@ enum qca_radiotap_vendor_ids {
*
* @QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS: Perform a standalone AOA (angle of
* arrival) measurement with a single peer. Specify peer MAC address in
- * QCA_WLAN_VENDOR_ATTR_MAC_ADDR and measurement type in
- * QCA_WLAN_VENDOR_ATTR_AOA_TYPE. Measurement result is reported in
+ * QCA_WLAN_VENDOR_ATTR_MAC_ADDR and optionally frequency (MHz) in
+ * QCA_WLAN_VENDOR_ATTR_FREQ (if not specified, locate peer in kernel
+ * scan results cache and use the frequency from there).
+ * Also specify measurement type in QCA_WLAN_VENDOR_ATTR_AOA_TYPE.
+ * Measurement result is reported in
* QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS_RESULT event.
*
* @QCA_NL80211_VENDOR_SUBCMD_AOA_ABORT_MEAS: Abort an AOA measurement. Specify
@@ -185,6 +265,265 @@ enum qca_radiotap_vendor_ids {
*
* @QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI: Get antenna RSSI value for a
* specific chain.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SECTOR_CFG: Get low level
+ * configuration for a DMG RF sector. Specify sector index in
+ * QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_INDEX, sector type in
+ * QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_TYPE and RF modules
+ * to return sector information for in
+ * QCA_WLAN_VENDOR_ATTR_DMG_RF_MODULE_MASK. Returns sector configuration
+ * in QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG. Also return the
+ * exact time where information was captured in
+ * QCA_WLAN_VENDOR_ATTR_TSF.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SECTOR_CFG: Set low level
+ * configuration for a DMG RF sector. Specify sector index in
+ * QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_INDEX, sector type in
+ * QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_TYPE and sector configuration
+ * for one or more DMG RF modules in
+ * QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SELECTED_SECTOR: Get selected
+ * DMG RF sector for a station. This is the sector that the HW
+ * will use to communicate with the station. Specify the MAC address
+ * of associated station/AP/PCP in QCA_WLAN_VENDOR_ATTR_MAC_ADDR (not
+ * needed for unassociated station). Specify sector type to return in
+ * QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_TYPE. Returns the selected
+ * sector index in QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_INDEX.
+ * Also return the exact time where the information was captured
+ * in QCA_WLAN_VENDOR_ATTR_TSF.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SELECTED_SECTOR: Set the
+ * selected DMG RF sector for a station. This is the sector that
+ * the HW will use to communicate with the station.
+ * Specify the MAC address of associated station/AP/PCP in
+ * QCA_WLAN_VENDOR_ATTR_MAC_ADDR, the sector type to select in
+ * QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_TYPE and the sector index
+ * in QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_INDEX.
+ * The selected sector will be locked such that it will not be
+ * modified like it normally does (for example when station
+ * moves around). To unlock the selected sector for a station
+ * pass the special value 0xFFFF in the sector index. To unlock
+ * all connected stations also pass a broadcast MAC address.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS: Configure the TDLS behavior
+ * in the host driver. The different TDLS configurations are defined
+ * by the attributes in enum qca_wlan_vendor_attr_tdls_configuration.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_GET_HE_CAPABILITIES: Query device IEEE 802.11ax HE
+ * capabilities. The response uses the attributes defined in
+ * enum qca_wlan_vendor_attr_get_he_capabilities.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN: Abort an ongoing vendor scan that was
+ * started with QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN. This command
+ * carries the scan cookie of the corresponding scan request. The scan
+ * cookie is represented by QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS: Set the Specific
+ * Absorption Rate (SAR) power limits. A critical regulation for
+ * FCC compliance, OEMs require methods to set SAR limits on TX
+ * power of WLAN/WWAN. enum qca_vendor_attr_sar_limits
+ * attributes are used with this command.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS: This command/event is used by the
+ * host driver for offloading the implementation of Auto Channel Selection
+ * (ACS) to an external user space entity. This interface is used as the
+ * event from the host driver to the user space entity and also as the
+ * request from the user space entity to the host driver. The event from
+ * the host driver is used by the user space entity as an indication to
+ * start the ACS functionality. The attributes used by this event are
+ * represented by the enum qca_wlan_vendor_attr_external_acs_event.
+ * User space entity uses the same interface to inform the host driver with
+ * selected channels after the ACS operation using the attributes defined
+ * by enum qca_wlan_vendor_attr_external_acs_channels.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_CHIP_PWRSAVE_FAILURE: Vendor event carrying the
+ * requisite information leading to a power save failure. The information
+ * carried as part of this event is represented by the
+ * enum qca_attr_chip_power_save_failure attributes.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET: Start/Stop the NUD statistics
+ * collection. Uses attributes defined in enum qca_attr_nud_stats_set.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET: Get the NUD statistics. These
+ * statistics are represented by the enum qca_attr_nud_stats_get
+ * attributes.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_FETCH_BSS_TRANSITION_STATUS: Sub-command to fetch
+ * the BSS transition status, whether accept or reject, for a list of
+ * candidate BSSIDs provided by the userspace. This uses the vendor
+ * attributes QCA_WLAN_VENDOR_ATTR_BTM_MBO_TRANSITION_REASON and
+ * QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO. The userspace shall specify
+ * the attributes QCA_WLAN_VENDOR_ATTR_BTM_MBO_TRANSITION_REASON and an
+ * array of QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_BSSID nested in
+ * QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO in the request. In the response
+ * the driver shall specify array of
+ * QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_BSSID and
+ * QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_STATUS pairs nested in
+ * QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL: Set the trace level for a
+ * specific QCA module. The trace levels are represented by
+ * enum qca_attr_trace_level attributes.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_BRP_SET_ANT_LIMIT: Set the Beam Refinement
+ * Protocol antenna limit in different modes. See enum
+ * qca_wlan_vendor_attr_brp_ant_limit_mode.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_START: Start spectral scan. The scan
+ * parameters are specified by enum qca_wlan_vendor_attr_spectral_scan.
+ * This returns a cookie (%QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COOKIE)
+ * identifying the operation in success case.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_STOP: Stop spectral scan. This uses
+ * a cookie (%QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COOKIE) from
+ * @QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_START to identify the scan to
+ * be stopped.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_ACTIVE_TOS: Set the active Type Of Service on the
+ * specific interface. This can be used to modify some of the low level
+ * scan parameters (off channel dwell time, home channel time) in the
+ * driver/firmware. These parameters are maintained within the host driver.
+ * This command is valid only when the interface is in the connected state.
+ * These scan parameters shall be reset by the driver/firmware once
+ * disconnected. The attributes used with this command are defined in
+ * enum qca_wlan_vendor_attr_active_tos.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_HANG: Event indicating to the user space that the
+ * driver has detected an internal failure. This event carries the
+ * information indicating the reason that triggered this detection. The
+ * attributes for this command are defined in
+ * enum qca_wlan_vendor_attr_hang.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_CONFIG: Get the current values
+ * of spectral parameters used. The spectral scan parameters are specified
+ * by enum qca_wlan_vendor_attr_spectral_scan.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_DIAG_STATS: Get the debug stats
+ * for spectral scan functionality. The debug stats are specified by
+ * enum qca_wlan_vendor_attr_spectral_diag_stats.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_CAP_INFO: Get spectral
+ * scan system capabilities. The capabilities are specified
+ * by enum qca_wlan_vendor_attr_spectral_cap.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_STATUS: Get the current
+ * status of spectral scan. The status values are specified
+ * by enum qca_wlan_vendor_attr_spectral_scan_status.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_PEER_FLUSH_PENDING: Sub-command to flush
+ * peer pending packets. Specify the peer MAC address in
+ * QCA_WLAN_VENDOR_ATTR_PEER_ADDR and the access category of the packets
+ * in QCA_WLAN_VENDOR_ATTR_AC. The attributes are listed
+ * in enum qca_wlan_vendor_attr_flush_pending.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_GET_RROP_INFO: Get vendor specific Representative
+ * RF Operating Parameter (RROP) information. The attributes for this
+ * information are defined in enum qca_wlan_vendor_attr_rrop_info. This is
+ * intended for use by external Auto Channel Selection applications.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS: Get the Specific Absorption Rate
+ * (SAR) power limits. This is a companion to the command
+ * @QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS and is used to retrieve the
+ * settings currently in use. The attributes returned by this command are
+ * defined by enum qca_vendor_attr_sar_limits.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO: Provides the current behavior of
+ * the WLAN hardware MAC. Also, provides the WLAN netdev interface
+ * information attached to the respective MAC.
+ * This works both as a query (user space asks the current mode) or event
+ * interface (driver advertising the current mode to the user space).
+ * Driver does not trigger this event for temporary hardware mode changes.
+ * Mode changes w.r.t Wi-Fi connection update (VIZ creation / deletion,
+ * channel change, etc.) are updated with this event. Attributes for this
+ * interface are defined in enum qca_wlan_vendor_attr_mac.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_SET_QDEPTH_THRESH: Set MSDU queue depth threshold
+ * per peer per TID. Attributes for this command are define in
+ * enum qca_wlan_set_qdepth_thresh_attr.
+ * @QCA_NL80211_VENDOR_SUBCMD_THERMAL_CMD: Provides the thermal shutdown action
+ * guide for WLAN driver. Request to suspend of driver and FW if the
+ * temperature is higher than the suspend threshold; resume action is
+ * requested to driver if the temperature is lower than the resume
+ * threshold. In user poll mode, request temperature data by user. For test
+ * purpose, getting thermal shutdown configuration parameters is needed.
+ * Attributes for this interface are defined in
+ * enum qca_wlan_vendor_attr_thermal_cmd.
+ * @QCA_NL80211_VENDOR_SUBCMD_THERMAL_EVENT: Thermal events reported from
+ * driver. Thermal temperature and indication of resume completion are
+ * reported as thermal events. The attributes for this command are defined
+ * in enum qca_wlan_vendor_attr_thermal_event.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION: Sub command to set WiFi
+ * test configuration. Attributes for this command are defined in
+ * enum qca_wlan_vendor_attr_wifi_test_config.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER: This command is used to configure an
+ * RX filter to receive frames from stations that are active on the
+ * operating channel, but not associated with the local device (e.g., STAs
+ * associated with other APs). Filtering is done based on a list of BSSIDs
+ * and STA MAC addresses added by the user. This command is also used to
+ * fetch the statistics of unassociated stations. The attributes used with
+ * this command are defined in enum qca_wlan_vendor_attr_bss_filter.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_NAN_EXT: An extendable version of NAN vendor
+ * command. The earlier command for NAN, QCA_NL80211_VENDOR_SUBCMD_NAN,
+ * carried a payload which was a binary blob of data. The command was not
+ * extendable to send more information. The newer version carries the
+ * legacy blob encapsulated within an attribute and can be extended with
+ * additional vendor attributes that can enhance the NAN command interface.
+ * @QCA_NL80211_VENDOR_SUBCMD_ROAM_SCAN_EVENT: Event to indicate scan triggered
+ * or stopped within driver/firmware in order to initiate roaming. The
+ * attributes used with this event are defined in enum
+ * qca_wlan_vendor_attr_roam_scan. Some drivers may not send these events
+ * in few cases, e.g., if the host processor is sleeping when this event
+ * is generated in firmware.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG: This command is used to
+ * configure parameters per peer to capture Channel Frequency Response
+ * (CFR) and enable Periodic CFR capture. The attributes for this command
+ * are defined in enum qca_wlan_vendor_peer_cfr_capture_attr.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT: Event to indicate changes
+ * in throughput dynamically. The driver estimates the throughput based on
+ * number of packets being transmitted/received per second and indicates
+ * the changes in throughput to user space. Userspace tools can use this
+ * information to configure kernel's TCP parameters in order to achieve
+ * peak throughput. Optionally, the driver will also send guidance on
+ * modifications to kernel's TCP parameters which can be referred by
+ * userspace tools. The attributes used with this event are defined in enum
+ * qca_wlan_vendor_attr_throughput_change.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_COEX_CONFIG: This command is used to set
+ * priorities among different types of traffic during coex scenarios.
+ * Current supported prioritization is among WLAN/BT/ZIGBEE with different
+ * profiles mentioned in enum qca_coex_config_profiles. The associated
+ * attributes used with this command are defined in enum
+ * qca_vendor_attr_coex_config.
+ *
+ * Based on the config provided, FW will boost the weight and prioritize
+ * the traffic for that subsystem (WLAN/BT/Zigbee).
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_AKMS: This command is used to query
+ * the supported AKM suite selectorss from the driver. It returns the list
+ * of supported AKMs in the attribute NL80211_ATTR_AKM_SUITES.
+ * @QCA_NL80211_VENDOR_SUBCMD_GET_FW_STATE: This command is used to get firmware
+ * state from the driver. It returns the firmware state in the attribute
+ * QCA_WLAN_VENDOR_ATTR_FW_STATE.
+ * @QCA_NL80211_VENDOR_SUBCMD_PEER_STATS_CACHE_FLUSH: This vendor subcommand
+ * is used by the driver to flush per-peer cached statistics to user space
+ * application. This interface is used as an event from the driver to
+ * user space application. Attributes for this event are specified in
+ * enum qca_wlan_vendor_attr_peer_stats_cache_params.
+ * QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_DATA attribute is expected to be
+ * sent in the event.
+ * @QCA_NL80211_VENDOR_SUBCMD_MPTA_HELPER_CONFIG: This sub command is used to
+ * improve the success rate of Zigbee joining network.
+ * Due to PTA master limitation, Zigbee joining network success rate is
+ * low while WLAN is working. The WLAN driver needs to configure some
+ * parameters including Zigbee state and specific WLAN periods to enhance
+ * PTA master. All these parameters are delivered by the attributes
+ * defined in enum qca_mpta_helper_vendor_attr.
*/
enum qca_nl80211_vendor_subcmds {
QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0,
@@ -194,7 +533,7 @@ enum qca_nl80211_vendor_subcmds {
QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY = 10,
QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY = 11,
QCA_NL80211_VENDOR_SUBCMD_NAN = 12,
- QCA_NL80211_VENDOR_SUBMCD_STATS_EXT = 13,
+ QCA_NL80211_VENDOR_SUBCMD_STATS_EXT = 13,
QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET = 14,
QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET = 15,
QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR = 16,
@@ -236,11 +575,33 @@ enum qca_nl80211_vendor_subcmds {
QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED = 58,
QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED = 59,
QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED = 60,
- /* 61-73 - reserved for QCA */
+ QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO = 61,
+ QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START = 62,
+ QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP = 63,
+ QCA_NL80211_VENDOR_SUBCMD_ROAM = 64,
+ QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_SSID_HOTLIST = 65,
+ QCA_NL80211_VENDOR_SUBCMD_GSCAN_RESET_SSID_HOTLIST = 66,
+ QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_SSID_FOUND = 67,
+ QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_SSID_LOST = 68,
+ QCA_NL80211_VENDOR_SUBCMD_PNO_SET_LIST = 69,
+ QCA_NL80211_VENDOR_SUBCMD_PNO_SET_PASSPOINT_LIST = 70,
+ QCA_NL80211_VENDOR_SUBCMD_PNO_RESET_PASSPOINT_LIST = 71,
+ QCA_NL80211_VENDOR_SUBCMD_PNO_NETWORK_FOUND = 72,
+ QCA_NL80211_VENDOR_SUBCMD_PNO_PASSPOINT_NETWORK_FOUND = 73,
/* Wi-Fi configuration subcommands */
QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION = 74,
QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION = 75,
- /* 76-90 - reserved for QCA */
+ QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET = 76,
+ QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA = 77,
+ QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES = 78,
+ QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS = 79,
+ QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI = 80,
+ QCA_NL80211_VENDOR_SUBCMD_NDP = 81,
+ QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD = 82,
+ QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER = 83,
+ QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE = 84,
+ QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS = 85,
+ /* 86-90 - reserved for QCA */
QCA_NL80211_VENDOR_SUBCMD_DATA_OFFLOAD = 91,
QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG = 92,
QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME = 93,
@@ -285,21 +646,70 @@ enum qca_nl80211_vendor_subcmds {
QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS_RESULT = 136,
QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST = 137,
QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI = 138,
+ /* DMG low level RF sector operations */
+ QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SECTOR_CFG = 139,
+ QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SECTOR_CFG = 140,
+ QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SELECTED_SECTOR = 141,
+ QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SELECTED_SECTOR = 142,
+ QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS = 143,
+ QCA_NL80211_VENDOR_SUBCMD_GET_HE_CAPABILITIES = 144,
+ QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN = 145,
+ QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS = 146,
+ QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS = 147,
+ QCA_NL80211_VENDOR_SUBCMD_CHIP_PWRSAVE_FAILURE = 148,
+ QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET = 149,
+ QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET = 150,
+ QCA_NL80211_VENDOR_SUBCMD_FETCH_BSS_TRANSITION_STATUS = 151,
+ QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL = 152,
+ QCA_NL80211_VENDOR_SUBCMD_BRP_SET_ANT_LIMIT = 153,
+ QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_START = 154,
+ QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_STOP = 155,
+ QCA_NL80211_VENDOR_SUBCMD_ACTIVE_TOS = 156,
+ QCA_NL80211_VENDOR_SUBCMD_HANG = 157,
+ QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_CONFIG = 158,
+ QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_DIAG_STATS = 159,
+ QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_CAP_INFO = 160,
+ QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_STATUS = 161,
+ /* Flush peer pending data */
+ QCA_NL80211_VENDOR_SUBCMD_PEER_FLUSH_PENDING = 162,
+ QCA_NL80211_VENDOR_SUBCMD_GET_RROP_INFO = 163,
+ QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS = 164,
+ QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO = 165,
+ QCA_NL80211_VENDOR_SUBCMD_SET_QDEPTH_THRESH = 166,
+ /* Thermal shutdown commands to protect wifi chip */
+ QCA_NL80211_VENDOR_SUBCMD_THERMAL_CMD = 167,
+ QCA_NL80211_VENDOR_SUBCMD_THERMAL_EVENT = 168,
+ /* Wi-Fi test configuration subcommand */
+ QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION = 169,
+ /* Frame filter operations for other BSSs/unassociated STAs */
+ QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER = 170,
+ QCA_NL80211_VENDOR_SUBCMD_NAN_EXT = 171,
+ QCA_NL80211_VENDOR_SUBCMD_ROAM_SCAN_EVENT = 172,
+ QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG = 173,
+ QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT = 174,
+ QCA_NL80211_VENDOR_SUBCMD_COEX_CONFIG = 175,
+ QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_AKMS = 176,
+ QCA_NL80211_VENDOR_SUBCMD_GET_FW_STATE = 177,
+ QCA_NL80211_VENDOR_SUBCMD_PEER_STATS_CACHE_FLUSH = 178,
+ QCA_NL80211_VENDOR_SUBCMD_MPTA_HELPER_CONFIG = 179,
};
-
enum qca_wlan_vendor_attr {
QCA_WLAN_VENDOR_ATTR_INVALID = 0,
/* used by QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY */
QCA_WLAN_VENDOR_ATTR_DFS = 1,
- /* used by QCA_NL80211_VENDOR_SUBCMD_NAN */
+ /* Used only when driver sends vendor events to the userspace under the
+ * command QCA_NL80211_VENDOR_SUBCMD_NAN. Not used when userspace sends
+ * commands to the driver.
+ */
QCA_WLAN_VENDOR_ATTR_NAN = 2,
/* used by QCA_NL80211_VENDOR_SUBCMD_STATS_EXT */
QCA_WLAN_VENDOR_ATTR_STATS_EXT = 3,
/* used by QCA_NL80211_VENDOR_SUBCMD_STATS_EXT */
QCA_WLAN_VENDOR_ATTR_IFINDEX = 4,
/* used by QCA_NL80211_VENDOR_SUBCMD_ROAMING, u32 with values defined
- * by enum qca_roaming_policy. */
+ * by enum qca_roaming_policy.
+ */
QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY = 5,
QCA_WLAN_VENDOR_ATTR_MAC_ADDR = 6,
/* used by QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES */
@@ -387,22 +797,147 @@ enum qca_wlan_vendor_attr {
QCA_WLAN_VENDOR_ATTR_AOA_MEAS_RESULT = 25,
/* Used in QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI command
* to specify the chain number (unsigned 32 bit value) to inquire
- * the corresponding antenna RSSI value */
+ * the corresponding antenna RSSI value
+ */
QCA_WLAN_VENDOR_ATTR_CHAIN_INDEX = 26,
/* Used in QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI command
- * to report the specific antenna RSSI value (unsigned 32 bit value) */
+ * to report the specific antenna RSSI value (unsigned 32 bit value)
+ */
QCA_WLAN_VENDOR_ATTR_CHAIN_RSSI = 27,
+ /* Frequency in MHz, various uses. Unsigned 32 bit value */
+ QCA_WLAN_VENDOR_ATTR_FREQ = 28,
+ /* TSF timer value, unsigned 64 bit value.
+ * May be returned by various commands.
+ */
+ QCA_WLAN_VENDOR_ATTR_TSF = 29,
+ /* DMG RF sector index, unsigned 16 bit number. Valid values are
+ * 0..127 for sector indices or 65535 as special value used to
+ * unlock sector selection in
+ * QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SELECTED_SECTOR.
+ */
+ QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_INDEX = 30,
+ /* DMG RF sector type, unsigned 8 bit value. One of the values
+ * in enum qca_wlan_vendor_attr_dmg_rf_sector_type.
+ */
+ QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_TYPE = 31,
+ /* Bitmask of DMG RF modules for which information is requested. Each
+ * bit corresponds to an RF module with the same index as the bit
+ * number. Unsigned 32 bit number but only low 8 bits can be set since
+ * all DMG chips currently have up to 8 RF modules.
+ */
+ QCA_WLAN_VENDOR_ATTR_DMG_RF_MODULE_MASK = 32,
+ /* Array of nested attributes where each entry is DMG RF sector
+ * configuration for a single RF module.
+ * Attributes for each entry are taken from enum
+ * qca_wlan_vendor_attr_dmg_rf_sector_cfg.
+ * Specified in QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SECTOR_CFG
+ * and returned by QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SECTOR_CFG.
+ */
+ QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG = 33,
+ /* Used in QCA_NL80211_VENDOR_SUBCMD_STATS_EXT command
+ * to report frame aggregation statistics to userspace.
+ */
+ QCA_WLAN_VENDOR_ATTR_RX_AGGREGATION_STATS_HOLES_NUM = 34,
+ QCA_WLAN_VENDOR_ATTR_RX_AGGREGATION_STATS_HOLES_INFO = 35,
+ /* Unsigned 8-bit value representing MBO transition reason code as
+ * provided by the AP used by subcommand
+ * QCA_NL80211_VENDOR_SUBCMD_FETCH_BSS_TRANSITION_STATUS. This is
+ * specified by the userspace in the request to the driver.
+ */
+ QCA_WLAN_VENDOR_ATTR_BTM_MBO_TRANSITION_REASON = 36,
+ /* Array of nested attributes, BSSID and status code, used by subcommand
+ * QCA_NL80211_VENDOR_SUBCMD_FETCH_BSS_TRANSITION_STATUS, where each
+ * entry is taken from enum qca_wlan_vendor_attr_btm_candidate_info.
+ * The userspace space specifies the list/array of candidate BSSIDs in
+ * the order of preference in the request. The driver specifies the
+ * status code, for each BSSID in the list, in the response. The
+ * acceptable candidates are listed in the order preferred by the
+ * driver.
+ */
+ QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO = 37,
+ /* Used in QCA_NL80211_VENDOR_SUBCMD_BRP_SET_ANT_LIMIT command
+ * See enum qca_wlan_vendor_attr_brp_ant_limit_mode.
+ */
+ QCA_WLAN_VENDOR_ATTR_BRP_ANT_LIMIT_MODE = 38,
+ /* Used in QCA_NL80211_VENDOR_SUBCMD_BRP_SET_ANT_LIMIT command
+ * to define the number of antennas to use for BRP.
+ * different purpose in each ANT_LIMIT_MODE:
+ * DISABLE - ignored
+ * EFFECTIVE - upper limit to number of antennas to be used
+ * FORCE - exact number of antennas to be used
+ * unsigned 8 bit value
+ */
+ QCA_WLAN_VENDOR_ATTR_BRP_ANT_NUM_LIMIT = 39,
+ /* Used in QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI command
+ * to report the corresponding antenna index to the chain RSSI value
+ */
+ QCA_WLAN_VENDOR_ATTR_ANTENNA_INFO = 40,
+ /* Used in QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI command to report
+ * the specific antenna EVM value (unsigned 32 bit value). With a
+ * determinate group of antennas, the driver specifies the EVM value
+ * for each antenna ID, and application extract them in user space.
+ */
+ QCA_WLAN_VENDOR_ATTR_CHAIN_EVM = 41,
+ /*
+ * Used in QCA_NL80211_VENDOR_SUBCMD_GET_FW_STATE command to report
+ * wlan firmware current state. FW state is an unsigned 8 bit value,
+ * one of the values in enum qca_wlan_vendor_attr_fw_state.
+ */
+ QCA_WLAN_VENDOR_ATTR_FW_STATE = 42,
+
/* keep last */
QCA_WLAN_VENDOR_ATTR_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_MAX = QCA_WLAN_VENDOR_ATTR_AFTER_LAST - 1,
};
-
enum qca_roaming_policy {
QCA_ROAMING_NOT_ALLOWED,
QCA_ROAMING_ALLOWED_WITHIN_ESS,
};
+/**
+ * enum qca_roam_reason - Represents the reason codes for roaming. Used by
+ * QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REASON.
+ *
+ * @QCA_ROAM_REASON_UNKNOWN: Any reason that do not classify under the below
+ * reasons.
+ *
+ * @QCA_ROAM_REASON_PER: Roam triggered when packet error rates (PER) breached
+ * the configured threshold.
+ *
+ * @QCA_ROAM_REASON_BEACON_MISS: Roam triggered due to the continuous configured
+ * beacon misses from the then connected AP.
+ *
+ * @QCA_ROAM_REASON_POOR_RSSI: Roam triggered due to the poor RSSI reported
+ * by the connected AP.
+ *
+ * @QCA_ROAM_REASON_BETTER_RSSI: Roam triggered for finding a BSS with a better
+ * RSSI than the connected BSS. Here the RSSI of the current BSS is not poor.
+ *
+ * @QCA_ROAM_REASON_CONGESTION: Roam triggered considering the connected channel
+ * or environment being very noisy or congested.
+ *
+ * @QCA_ROAM_REASON_EXPLICIT_REQUEST: Roam triggered due to an explicit request
+ * from the user (user space).
+ *
+ * @QCA_ROAM_REASON_BTM: Roam triggered due to BTM Request frame received from
+ * the connected AP.
+ *
+ * @QCA_ROAM_REASON_BSS_LOAD: Roam triggered due to the channel utilization
+ * breaching out the configured threshold.
+ */
+enum qca_roam_reason {
+ QCA_ROAM_REASON_UNKNOWN,
+ QCA_ROAM_REASON_PER,
+ QCA_ROAM_REASON_BEACON_MISS,
+ QCA_ROAM_REASON_POOR_RSSI,
+ QCA_ROAM_REASON_BETTER_RSSI,
+ QCA_ROAM_REASON_CONGESTION,
+ QCA_ROAM_REASON_USER_TRIGGER,
+ QCA_ROAM_REASON_BTM,
+ QCA_ROAM_REASON_BSS_LOAD,
+};
+
enum qca_wlan_vendor_attr_roam_auth {
QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_INVALID = 0,
QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
@@ -413,6 +948,43 @@ enum qca_wlan_vendor_attr_roam_auth {
QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
+ /* Indicates the status of re-association requested by user space for
+ * the BSSID specified by QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID.
+ * Type u16.
+ * Represents the status code from AP. Use
+ * %WLAN_STATUS_UNSPECIFIED_FAILURE if the device cannot give you the
+ * real status code for failures.
+ */
+ QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_STATUS,
+ /* This attribute indicates that the old association was maintained when
+ * a re-association is requested by user space and that re-association
+ * attempt fails (i.e., cannot connect to the requested BSS, but can
+ * remain associated with the BSS with which the association was in
+ * place when being requested to roam). Used along with
+ * WLAN_VENDOR_ATTR_ROAM_AUTH_STATUS to indicate the current
+ * re-association status. Type flag.
+ * This attribute is applicable only for re-association failure cases.
+ */
+ QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RETAIN_CONNECTION,
+ /* This attribute specifies the PMK if one was newly generated during
+ * FILS roaming. This is added to the PMKSA cache and is used in
+ * subsequent connections with PMKSA caching.
+ */
+ QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMK = 11,
+ /* This attribute specifies the PMKID used/generated for the current
+ * FILS roam. This is used in subsequent connections with PMKSA caching.
+ */
+ QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMKID = 12,
+ /* A 16-bit unsigned value specifying the next sequence number to use
+ * in ERP message in the currently associated realm. This is used in
+ * doing subsequent ERP based connections in the same realm.
+ */
+ QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_FILS_ERP_NEXT_SEQ_NUM = 13,
+ /* A 16-bit unsigned value representing the reasons for the roaming.
+ * Defined by enum qca_roam_reason.
+ */
+ QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REASON = 14,
+
/* keep last */
QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_MAX =
@@ -493,13 +1065,25 @@ enum qca_wlan_vendor_acs_hw_mode {
* @QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY: Device supports automatic
* band selection based on channel selection results.
* @QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS: Device supports
- * simultaneous off-channel operations.
+ * simultaneous off-channel operations.
* @QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD: Device supports P2P
* Listen offload; a mechanism where the station's firmware takes care of
* responding to incoming Probe Request frames received from other P2P
* Devices whilst in Listen state, rather than having the user space
* wpa_supplicant do it. Information from received P2P requests are
* forwarded from firmware to host whenever the host processor wakes up.
+ * @QCA_WLAN_VENDOR_FEATURE_OCE_STA: Device supports all OCE non-AP STA
+ * specific features.
+ * @QCA_WLAN_VENDOR_FEATURE_OCE_AP: Device supports all OCE AP specific
+ * features.
+ * @QCA_WLAN_VENDOR_FEATURE_OCE_STA_CFON: Device supports OCE STA-CFON
+ * specific features only. If a Device sets this bit but not the
+ * %QCA_WLAN_VENDOR_FEATURE_OCE_AP, the userspace shall assume that
+ * this Device may not support all OCE AP functionalities but can support
+ * only OCE STA-CFON functionalities.
+ * @QCA_WLAN_VENDOR_FEATURE_SELF_MANAGED_REGULATORY: Device supports self
+ * managed regulatory.
+ * @QCA_WLAN_VENDOR_FEATURE_TWT: Device supports TWT (Target Wake Time).
* @NUM_QCA_WLAN_VENDOR_FEATURES: Number of assigned feature bits
*/
enum qca_wlan_vendor_features {
@@ -507,6 +1091,11 @@ enum qca_wlan_vendor_features {
QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY = 1,
QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS = 2,
QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD = 3,
+ QCA_WLAN_VENDOR_FEATURE_OCE_STA = 4,
+ QCA_WLAN_VENDOR_FEATURE_OCE_AP = 5,
+ QCA_WLAN_VENDOR_FEATURE_OCE_STA_CFON = 6,
+ QCA_WLAN_VENDOR_FEATURE_SELF_MANAGED_REGULATORY = 7,
+ QCA_WLAN_VENDOR_FEATURE_TWT = 8,
NUM_QCA_WLAN_VENDOR_FEATURES /* keep last */
};
@@ -532,6 +1121,112 @@ enum qca_wlan_vendor_attr_data_offload_ind {
QCA_WLAN_VENDOR_ATTR_DATA_OFFLOAD_IND_AFTER_LAST - 1
};
+/**
+ * enum qca_wlan_vendor_attr_ocb_set_config - Vendor subcmd attributes to set
+ * OCB config
+ *
+ * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_CHANNEL_COUNT: Number of channels in the
+ * configuration
+ * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_SCHEDULE_SIZE: Size of the schedule
+ * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_CHANNEL_ARRAY: Array of channels
+ * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_SCHEDULE_ARRAY: Array of channels to be
+ * scheduled
+ * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_NDL_CHANNEL_ARRAY: Array of NDL channel
+ * information
+ * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_NDL_ACTIVE_STATE_ARRAY: Array of NDL
+ * active state configuration
+ * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_FLAGS: Configuration flags such as
+ * OCB_CONFIG_FLAG_80211_FRAME_MODE
+ * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_DEF_TX_PARAM: Default TX parameters to
+ * use in the case that a packet is sent without a TX control header
+ * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_TA_MAX_DURATION: Max duration after the
+ * last TA received that the local time set by TA is synchronous to other
+ * communicating OCB STAs.
+ */
+enum qca_wlan_vendor_attr_ocb_set_config {
+ QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_CHANNEL_COUNT = 1,
+ QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_SCHEDULE_SIZE = 2,
+ QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_CHANNEL_ARRAY = 3,
+ QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_SCHEDULE_ARRAY = 4,
+ QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_NDL_CHANNEL_ARRAY = 5,
+ QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_NDL_ACTIVE_STATE_ARRAY = 6,
+ QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_FLAGS = 7,
+ QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_DEF_TX_PARAM = 8,
+ QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_TA_MAX_DURATION = 9,
+ QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_MAX =
+ QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_AFTER_LAST - 1
+};
+
+/**
+ * enum qca_wlan_vendor_attr_ocb_set_utc_time - Vendor subcmd attributes to set
+ * UTC time
+ *
+ * @QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_VALUE: The UTC time as an array of
+ * 10 bytes
+ * @QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_ERROR: The time error as an array of
+ * 5 bytes
+ */
+enum qca_wlan_vendor_attr_ocb_set_utc_time {
+ QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_VALUE = 1,
+ QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_ERROR = 2,
+ QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_MAX =
+ QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_AFTER_LAST - 1
+};
+
+/**
+ * enum qca_wlan_vendor_attr_ocb_start_timing_advert - Vendor subcmd attributes
+ * to start sending timing advert frames
+ *
+ * @QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_CHANNEL_FREQ: Cannel frequency
+ * on which to send the frames
+ * @QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_REPEAT_RATE: Number of times
+ * the frame is sent in 5 seconds
+ */
+enum qca_wlan_vendor_attr_ocb_start_timing_advert {
+ QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_CHANNEL_FREQ = 1,
+ QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_REPEAT_RATE = 2,
+ QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_MAX =
+ QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_AFTER_LAST - 1
+};
+
+/**
+ * enum qca_wlan_vendor_attr_ocb_stop_timing_advert - Vendor subcmd attributes
+ * to stop timing advert
+ *
+ * @QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_CHANNEL_FREQ: The channel
+ * frequency on which to stop the timing advert
+ */
+enum qca_wlan_vendor_attr_ocb_stop_timing_advert {
+ QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_CHANNEL_FREQ = 1,
+ QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_MAX =
+ QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_AFTER_LAST - 1
+};
+
+/**
+ * enum qca_wlan_vendor_attr_ocb_get_tsf_response - Vendor subcmd attributes to
+ * get TSF timer value
+ *
+ * @QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_HIGH: Higher 32 bits of the
+ * timer
+ * @QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_LOW: Lower 32 bits of the timer
+ */
+enum qca_wlan_vendor_attr_ocb_get_tsf_resp {
+ QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_HIGH = 1,
+ QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_LOW = 2,
+ QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_MAX =
+ QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_AFTER_LAST - 1
+};
+
enum qca_vendor_attr_get_preferred_freq_list {
QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_INVALID,
/* A 32-unsigned value; the interface type/mode for which the preferred
@@ -544,6 +1239,12 @@ enum qca_vendor_attr_get_preferred_freq_list {
* from kernel space to user space.
*/
QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
+ /* An array of nested values as per enum qca_wlan_vendor_attr_pcl
+ * attribute. Each element contains frequency (MHz), weight, and flag
+ * bit mask indicating how the frequency should be used in P2P
+ * negotiation; sent from kernel space to user space.
+ */
+ QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_WEIGHED_PCL,
/* keep last */
QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX =
@@ -679,11 +1380,39 @@ enum qca_vendor_attr_wisa_cmd {
* vendor specific element is defined by the latest P802.11ax draft.
* Please note that the draft is still work in progress and this element
* payload is subject to change.
+ *
+ * @QCA_VENDOR_ELEM_RAPS: RAPS element (OFDMA-based Random Access Parameter Set
+ * element).
+ * This element can be used for pre-standard publication testing of HE
+ * before P802.11ax draft assigns the element ID extension. The payload of
+ * this vendor specific element is defined by the latest P802.11ax draft
+ * (not including the Element ID Extension field). Please note that the
+ * draft is still work in progress and this element payload is subject to
+ * change.
+ *
+ * @QCA_VENDOR_ELEM_MU_EDCA_PARAMS: MU EDCA Parameter Set element.
+ * This element can be used for pre-standard publication testing of HE
+ * before P802.11ax draft assigns the element ID extension. The payload of
+ * this vendor specific element is defined by the latest P802.11ax draft
+ * (not including the Element ID Extension field). Please note that the
+ * draft is still work in progress and this element payload is subject to
+ * change.
+ *
+ * @QCA_VENDOR_ELEM_BSS_COLOR_CHANGE: BSS Color Change Announcement element.
+ * This element can be used for pre-standard publication testing of HE
+ * before P802.11ax draft assigns the element ID extension. The payload of
+ * this vendor specific element is defined by the latest P802.11ax draft
+ * (not including the Element ID Extension field). Please note that the
+ * draft is still work in progress and this element payload is subject to
+ * change.
*/
enum qca_vendor_element_id {
QCA_VENDOR_ELEM_P2P_PREF_CHAN_LIST = 0,
QCA_VENDOR_ELEM_HE_CAPAB = 1,
QCA_VENDOR_ELEM_HE_OPER = 2,
+ QCA_VENDOR_ELEM_RAPS = 3,
+ QCA_VENDOR_ELEM_MU_EDCA_PARAMS = 4,
+ QCA_VENDOR_ELEM_BSS_COLOR_CHANGE = 5,
};
/**
@@ -696,29 +1425,32 @@ enum qca_vendor_element_id {
* @QCA_WLAN_VENDOR_ATTR_SCAN_SUPP_RATES: Nested array attribute of supported
* rates to be included
* @QCA_WLAN_VENDOR_ATTR_SCAN_TX_NO_CCK_RATE: flag used to send probe requests
- * at non CCK rate in 2GHz band
+ * at non CCK rate in 2GHz band
* @QCA_WLAN_VENDOR_ATTR_SCAN_FLAGS: Unsigned 32-bit scan flags
* @QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE: Unsigned 64-bit cookie provided by the
- * driver for the specific scan request
+ * driver for the specific scan request
* @QCA_WLAN_VENDOR_ATTR_SCAN_STATUS: Unsigned 8-bit status of the scan
- * request decoded as in enum scan_status
+ * request decoded as in enum scan_status
* @QCA_WLAN_VENDOR_ATTR_SCAN_MAC: 6-byte MAC address to use when randomisation
- * scan flag is set
+ * scan flag is set
* @QCA_WLAN_VENDOR_ATTR_SCAN_MAC_MASK: 6-byte MAC address mask to be used with
- * randomisation
+ * randomisation
+ * @QCA_WLAN_VENDOR_ATTR_SCAN_BSSID: 6-byte MAC address representing the
+ * specific BSSID to scan for.
*/
enum qca_wlan_vendor_attr_scan {
QCA_WLAN_VENDOR_ATTR_SCAN_INVALID_PARAM = 0,
- QCA_WLAN_VENDOR_ATTR_SCAN_IE,
- QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES,
- QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS,
- QCA_WLAN_VENDOR_ATTR_SCAN_SUPP_RATES,
- QCA_WLAN_VENDOR_ATTR_SCAN_TX_NO_CCK_RATE,
- QCA_WLAN_VENDOR_ATTR_SCAN_FLAGS,
- QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE,
- QCA_WLAN_VENDOR_ATTR_SCAN_STATUS,
- QCA_WLAN_VENDOR_ATTR_SCAN_MAC,
- QCA_WLAN_VENDOR_ATTR_SCAN_MAC_MASK,
+ QCA_WLAN_VENDOR_ATTR_SCAN_IE = 1,
+ QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES = 2,
+ QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS = 3,
+ QCA_WLAN_VENDOR_ATTR_SCAN_SUPP_RATES = 4,
+ QCA_WLAN_VENDOR_ATTR_SCAN_TX_NO_CCK_RATE = 5,
+ QCA_WLAN_VENDOR_ATTR_SCAN_FLAGS = 6,
+ QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE = 7,
+ QCA_WLAN_VENDOR_ATTR_SCAN_STATUS = 8,
+ QCA_WLAN_VENDOR_ATTR_SCAN_MAC = 9,
+ QCA_WLAN_VENDOR_ATTR_SCAN_MAC_MASK = 10,
+ QCA_WLAN_VENDOR_ATTR_SCAN_BSSID = 11,
QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_SCAN_MAX =
QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST - 1
@@ -726,10 +1458,10 @@ enum qca_wlan_vendor_attr_scan {
/**
* enum scan_status - Specifies the valid values the vendor scan attribute
- * QCA_WLAN_VENDOR_ATTR_SCAN_STATUS can take
+ * QCA_WLAN_VENDOR_ATTR_SCAN_STATUS can take
*
* @VENDOR_SCAN_STATUS_NEW_RESULTS: implies the vendor scan is successful with
- * new scan results
+ * new scan results
* @VENDOR_SCAN_STATUS_ABORTED: implies the vendor scan was aborted in-between
*/
enum scan_status {
@@ -776,7 +1508,8 @@ enum qca_vendor_attr_txpower_scale {
enum qca_vendor_attr_txpower_decr_db {
QCA_WLAN_VENDOR_ATTR_TXPOWER_DECR_DB_INVALID,
/* 8-bit unsigned value to indicate the reduction of TX power in dB for
- * a virtual interface. */
+ * a virtual interface.
+ */
QCA_WLAN_VENDOR_ATTR_TXPOWER_DECR_DB,
/* keep last */
QCA_WLAN_VENDOR_ATTR_TXPOWER_DECR_DB_AFTER_LAST,
@@ -826,29 +1559,37 @@ enum qca_wlan_vendor_attr_config {
*/
QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND = 7,
/* 8-bit unsigned value to configure the maximum TX MPDU for
- * aggregation. */
+ * aggregation.
+ */
QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION = 8,
/* 8-bit unsigned value to configure the maximum RX MPDU for
- * aggregation. */
+ * aggregation.
+ */
QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION = 9,
/* 8-bit unsigned value to configure the Non aggregrate/11g sw
- * retry threshold (0 disable, 31 max). */
+ * retry threshold (0 disable, 31 max).
+ */
QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY = 10,
/* 8-bit unsigned value to configure the aggregrate sw
- * retry threshold (0 disable, 31 max). */
+ * retry threshold (0 disable, 31 max).
+ */
QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY = 11,
/* 8-bit unsigned value to configure the MGMT frame
- * retry threshold (0 disable, 31 max). */
+ * retry threshold (0 disable, 31 max).
+ */
QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY = 12,
/* 8-bit unsigned value to configure the CTRL frame
- * retry threshold (0 disable, 31 max). */
+ * retry threshold (0 disable, 31 max).
+ */
QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY = 13,
/* 8-bit unsigned value to configure the propagation delay for
- * 2G/5G band (0~63, units in us) */
+ * 2G/5G band (0~63, units in us)
+ */
QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY = 14,
/* Unsigned 32-bit value to configure the number of unicast TX fail
* packet count. The peer is disconnected once this threshold is
- * reached. */
+ * reached.
+ */
QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT = 15,
/* Attribute used to set scan default IEs to the driver.
*
@@ -859,7 +1600,8 @@ enum qca_wlan_vendor_attr_config {
* merged with the IEs received along with scan request coming to the
* driver. If a particular IE is present in the scan default IEs but not
* present in the scan request, then that IE should be added to the IEs
- * sent in the Probe Request frames for that scan request. */
+ * sent in the Probe Request frames for that scan request.
+ */
QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES = 16,
/* Unsigned 32-bit attribute for generic commands */
QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_COMMAND = 17,
@@ -868,42 +1610,183 @@ enum qca_wlan_vendor_attr_config {
/* Unsigned 32-bit data attribute for generic command response */
QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA = 19,
/* Unsigned 32-bit length attribute for
- * QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA */
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA
+ */
QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_LENGTH = 20,
/* Unsigned 32-bit flags attribute for
- * QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA */
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA
+ */
QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_FLAGS = 21,
/* Unsigned 32-bit, defining the access policy.
* See enum qca_access_policy. Used with
- * QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST. */
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST.
+ */
QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY = 22,
/* Sets the list of full set of IEs for which a specific access policy
* has to be applied. Used along with
* QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY to control the access.
- * Zero length payload can be used to clear this access constraint. */
+ * Zero length payload can be used to clear this access constraint.
+ */
QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST = 23,
/* Unsigned 32-bit, specifies the interface index (netdev) for which the
* corresponding configurations are applied. If the interface index is
* not specified, the configurations are attributed to the respective
- * wiphy. */
+ * wiphy.
+ */
QCA_WLAN_VENDOR_ATTR_CONFIG_IFINDEX = 24,
/* 8-bit unsigned value to trigger QPower: 1-Enable, 0-Disable */
QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER = 25,
/* 8-bit unsigned value to configure the driver and below layers to
* ignore the assoc disallowed set by APs while connecting
- * 1-Ignore, 0-Don't ignore */
+ * 1-Ignore, 0-Don't ignore
+ */
QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED = 26,
/* 32-bit unsigned value to trigger antenna diversity features:
- * 1-Enable, 0-Disable */
+ * 1-Enable, 0-Disable
+ */
QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA = 27,
/* 32-bit unsigned value to configure specific chain antenna */
QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN = 28,
/* 32-bit unsigned value to trigger cycle selftest
- * 1-Enable, 0-Disable */
+ * 1-Enable, 0-Disable
+ */
QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST = 29,
/* 32-bit unsigned to configure the cycle time of selftest
- * the unit is micro-second */
+ * the unit is micro-second
+ */
QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST_INTVL = 30,
+ /* 32-bit unsigned value to set reorder timeout for AC_VO */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VOICE = 31,
+ /* 32-bit unsigned value to set reorder timeout for AC_VI */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VIDEO = 32,
+ /* 32-bit unsigned value to set reorder timeout for AC_BE */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BESTEFFORT = 33,
+ /* 32-bit unsigned value to set reorder timeout for AC_BK */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BACKGROUND = 34,
+ /* 6-byte MAC address to point out the specific peer */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_PEER_MAC = 35,
+ /* 32-bit unsigned value to set window size for specific peer */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_WINLIMIT = 36,
+ /* 8-bit unsigned value to set the beacon miss threshold in 2.4 GHz */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_MISS_THRESHOLD_24 = 37,
+ /* 8-bit unsigned value to set the beacon miss threshold in 5 GHz */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_MISS_THRESHOLD_5 = 38,
+ /* 32-bit unsigned value to configure 5 or 10 MHz channel width for
+ * station device while in disconnect state. The attribute use the
+ * value of enum nl80211_chan_width: NL80211_CHAN_WIDTH_5 means 5 MHz,
+ * NL80211_CHAN_WIDTH_10 means 10 MHz. If set, the device work in 5 or
+ * 10 MHz channel width, the station will not connect to a BSS using 20
+ * MHz or higher bandwidth. Set to NL80211_CHAN_WIDTH_20_NOHT to
+ * clear this constraint.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_SUB20_CHAN_WIDTH = 39,
+ /* 32-bit unsigned value to configure the propagation absolute delay
+ * for 2G/5G band (units in us)
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY = 40,
+ /* 32-bit unsigned value to set probe period */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_PERIOD = 41,
+ /* 32-bit unsigned value to set stay period */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_STAY_PERIOD = 42,
+ /* 32-bit unsigned value to set snr diff */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SNR_DIFF = 43,
+ /* 32-bit unsigned value to set probe dwell time */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_DWELL_TIME = 44,
+ /* 32-bit unsigned value to set mgmt snr weight */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_MGMT_SNR_WEIGHT = 45,
+ /* 32-bit unsigned value to set data snr weight */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_DATA_SNR_WEIGHT = 46,
+ /* 32-bit unsigned value to set ack snr weight */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ACK_SNR_WEIGHT = 47,
+ /* 32-bit unsigned value to configure the listen interval.
+ * This is in units of beacon intervals. This configuration alters
+ * the negotiated listen interval with the AP during the connection.
+ * It is highly recommended to configure a value less than or equal to
+ * the one negotiated during the association. Configuring any greater
+ * value can have adverse effects (frame loss, AP disassociating STA,
+ * etc.).
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL = 48,
+ /*
+ * 8 bit unsigned value that is set on an AP/GO virtual interface to
+ * disable operations that would cause the AP/GO to leave its operating
+ * channel.
+ *
+ * This will restrict the scans to the AP/GO operating channel and the
+ * channels of the other band, if DBS is supported.A STA/CLI interface
+ * brought up after this setting is enabled, will be restricted to
+ * connecting to devices only on the AP/GO interface's operating channel
+ * or on the other band in DBS case. P2P supported channel list is
+ * modified, to only include AP interface's operating-channel and the
+ * channels of the other band if DBS is supported.
+ *
+ * These restrictions are only applicable as long as the AP/GO interface
+ * is alive. If the AP/GO interface is brought down then this
+ * setting/restriction is forgotten.
+ *
+ * If this variable is set on an AP/GO interface while a multi-channel
+ * concurrent session is active, it has no effect on the operation of
+ * the current interfaces, other than restricting the scan to the AP/GO
+ * operating channel and the other band channels if DBS is supported.
+ * However, if the STA is brought down and restarted then the new STA
+ * connection will either be formed on the AP/GO channel or on the
+ * other band in a DBS case. This is because of the scan being
+ * restricted on these channels as mentioned above.
+ *
+ * 1-Restrict / 0-Don't restrict offchannel operations.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL = 49,
+ /*
+ * 8 bit unsigned value to enable/disable LRO (Large Receive Offload)
+ * on an interface.
+ * 1 - Enable, 0 - Disable.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_LRO = 50,
+
+ /*
+ * 8 bit unsigned value to globally enable/disable scan
+ * 1 - Enable, 0 - Disable.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_ENABLE = 51,
+
+ /* 8-bit unsigned value to set the total beacon miss count
+ * This parameter will set the total beacon miss count.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_TOTAL_BEACON_MISS_COUNT = 52,
+
+ /* Unsigned 32-bit value to configure the number of continuous
+ * Beacon Miss which shall be used by the firmware to penalize
+ * the RSSI for BTC.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_PENALIZE_AFTER_NCONS_BEACON_MISS_BTC = 53,
+
+ /* 8-bit unsigned value to configure the driver and below layers to
+ * enable/disable all FILS features.
+ * 0-enable, 1-disable
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_DISABLE_FILS = 54,
+
+ /* 16-bit unsigned value to configure the level of WLAN latency
+ * module. See enum qca_wlan_vendor_attr_config_latency_level.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL = 55,
+
+ /* 8-bit unsigned value indicating the driver to use the RSNE as-is from
+ * the connect interface. Exclusively used for the scenarios where the
+ * device is used as a test bed device with special functionality and
+ * not recommended for production. This helps driver to not validate the
+ * RSNE passed from user space and thus allow arbitrary IE data to be
+ * used for testing purposes.
+ * 1-enable, 0-disable.
+ * Applications set/reset this configuration. If not reset, this
+ * parameter remains in use until the driver is unloaded.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE = 56,
+
+ /* 8-bit unsigned value to trigger green Tx power saving.
+ * 1-Enable, 0-Disable
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_GTX = 57,
/* keep last */
QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST,
@@ -937,7 +1820,8 @@ enum qca_wlan_vendor_attr_sap_config {
enum qca_wlan_vendor_attr_sap_conditional_chan_switch {
QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_INVALID = 0,
/* Priority based frequency list (an array of u32 values in host byte
- * order) */
+ * order)
+ */
QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST = 1,
/* Status of the conditional switch (u32).
* 0: Success, Non-zero: Failure
@@ -972,6 +1856,36 @@ enum qca_wlan_gpio_attr {
};
/**
+ * qca_wlan_set_qdepth_thresh_attr - Parameters for setting
+ * MSDUQ depth threshold per peer per tid in the target
+ *
+ * Associated Vendor Command:
+ * QCA_NL80211_VENDOR_SUBCMD_SET_QDEPTH_THRESH
+ */
+enum qca_wlan_set_qdepth_thresh_attr {
+ QCA_WLAN_VENDOR_ATTR_QDEPTH_THRESH_INVALID = 0,
+ /* 6-byte MAC address */
+ QCA_WLAN_VENDOR_ATTR_QDEPTH_THRESH_MAC_ADDR,
+ /* Unsigned 32-bit attribute for holding the TID */
+ QCA_WLAN_VENDOR_ATTR_QDEPTH_THRESH_TID,
+ /* Unsigned 32-bit attribute for holding the update mask
+ * bit 0 - Update high priority msdu qdepth threshold
+ * bit 1 - Update low priority msdu qdepth threshold
+ * bit 2 - Update UDP msdu qdepth threshold
+ * bit 3 - Update Non UDP msdu qdepth threshold
+ * rest of bits are reserved
+ */
+ QCA_WLAN_VENDOR_ATTR_QDEPTH_THRESH_UPDATE_MASK,
+ /* Unsigned 32-bit attribute for holding the threshold value */
+ QCA_WLAN_VENDOR_ATTR_QDEPTH_THRESH_VALUE,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_QDEPTH_THRESH_LAST,
+ QCA_WLAN_VENDOR_ATTR_QDEPTH_THRESH_MAX =
+ QCA_WLAN_VENDOR_ATTR_QDEPTH_THRESH_LAST - 1,
+};
+
+/**
* enum qca_wlan_vendor_attr_get_hw_capability - Wi-Fi hardware capability
*/
enum qca_wlan_vendor_attr_get_hw_capability {
@@ -1143,6 +2057,12 @@ enum qca_wlan_vendor_attr_get_hw_capability {
* @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_ANT_NF: per antenna NF value
* @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IFACE_RSSI_BEACON: RSSI of beacon
* @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IFACE_SNR_BEACON: SNR of beacon
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_REPORT_TIME: u64
+ * Absolute timestamp from 1970/1/1, unit in ms. After receiving the
+ * message, user layer APP could call gettimeofday to get another
+ * timestamp and calculate transfer delay for the message.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_MEASUREMENT_TIME: u32
+ * Real period for this measurement, unit in us.
*/
enum qca_wlan_vendor_attr_ll_stats_ext {
QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_INVALID = 0,
@@ -1236,6 +2156,9 @@ enum qca_wlan_vendor_attr_ll_stats_ext {
QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IFACE_RSSI_BEACON,
QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IFACE_SNR_BEACON,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_REPORT_TIME,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_MEASUREMENT_TIME,
+
QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_LAST,
QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_MAX =
QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_LAST - 1
@@ -1289,7 +2212,7 @@ enum qca_wlan_vendor_attr_loc_capa {
* @QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_FTM_INITIATOR: Set if driver
* can run FTM sessions. QCA_NL80211_VENDOR_SUBCMD_FTM_START_SESSION
* will be supported if set.
-* @QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_ASAP: Set if FTM responder
+ * @QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_ASAP: Set if FTM responder
* supports immediate (ASAP) response.
* @QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_AOA: Set if driver supports standalone
* AOA measurement using QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS.
@@ -1320,6 +2243,10 @@ enum qca_wlan_vendor_attr_loc_capa_flags {
* @QCA_WLAN_VENDOR_ATTR_FTM_PEER_AOA_BURST_PERIOD: Request AOA
* measurement every <value> bursts. If 0 or not specified,
* AOA measurements will be disabled for this peer.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_FREQ: Frequency in MHz where
+ * the measurement frames are exchanged. Optional; if not
+ * specified, try to locate the peer in the kernel scan
+ * results cache and use frequency from there.
*/
enum qca_wlan_vendor_attr_ftm_peer_info {
QCA_WLAN_VENDOR_ATTR_FTM_PEER_INVALID,
@@ -1328,6 +2255,7 @@ enum qca_wlan_vendor_attr_ftm_peer_info {
QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_PARAMS,
QCA_WLAN_VENDOR_ATTR_FTM_PEER_SECURE_TOKEN_ID,
QCA_WLAN_VENDOR_ATTR_FTM_PEER_AOA_BURST_PERIOD,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_FREQ,
/* keep last */
QCA_WLAN_VENDOR_ATTR_FTM_PEER_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_FTM_PEER_MAX =
@@ -1587,4 +2515,4198 @@ enum qca_wlan_vendor_attr_encryption_test {
QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_AFTER_LAST - 1
};
+/**
+ * enum qca_wlan_vendor_attr_dmg_rf_sector_type - Type of
+ * sector for DMG RF sector operations.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_TYPE_RX: RX sector
+ * @QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_TYPE_TX: TX sector
+ */
+enum qca_wlan_vendor_attr_dmg_rf_sector_type {
+ QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_TYPE_RX,
+ QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_TYPE_TX,
+ QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_TYPE_MAX
+};
+
+/**
+ * enum qca_wlan_vendor_attr_fw_state - State of firmware
+ *
+ * @QCA_WLAN_VENDOR_ATTR_FW_STATE_ERROR: FW is in bad state
+ * @QCA_WLAN_VENDOR_ATTR_FW_STATE_ACTIVE: FW is active
+ */
+enum qca_wlan_vendor_attr_fw_state {
+ QCA_WLAN_VENDOR_ATTR_FW_STATE_ERROR,
+ QCA_WLAN_VENDOR_ATTR_FW_STATE_ACTIVE,
+ QCA_WLAN_VENDOR_ATTR_FW_STATE_MAX
+};
+
+/**
+ * BRP antenna limit mode
+ *
+ * @QCA_WLAN_VENDOR_ATTR_BRP_ANT_LIMIT_MODE_DISABLE: Disable BRP force
+ * antenna limit, BRP will be performed as usual.
+ * @QCA_WLAN_VENDOR_ATTR_BRP_ANT_LIMIT_MODE_EFFECTIVE: Define maximal
+ * antennas limit. the hardware may use less antennas than the
+ * maximum limit.
+ * @QCA_WLAN_VENDOR_ATTR_BRP_ANT_LIMIT_MODE_FORCE: The hardware will
+ * use exactly the specified number of antennas for BRP.
+ */
+enum qca_wlan_vendor_attr_brp_ant_limit_mode {
+ QCA_WLAN_VENDOR_ATTR_BRP_ANT_LIMIT_MODE_DISABLE,
+ QCA_WLAN_VENDOR_ATTR_BRP_ANT_LIMIT_MODE_EFFECTIVE,
+ QCA_WLAN_VENDOR_ATTR_BRP_ANT_LIMIT_MODE_FORCE,
+ QCA_WLAN_VENDOR_ATTR_BRP_ANT_LIMIT_MODE_MAX
+};
+
+/**
+ * enum qca_wlan_vendor_attr_dmg_rf_sector_cfg - Attributes for
+ * DMG RF sector configuration for a single RF module.
+ * The values are defined in a compact way which closely matches
+ * the way it is stored in HW registers.
+ * The configuration provides values for 32 antennas and 8 distribution
+ * amplifiers, and together describes the characteristics of the RF
+ * sector - such as a beam in some direction with some gain.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_MODULE_INDEX: Index
+ * of RF module for this configuration.
+ * @QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_ETYPE0: Bit 0 of edge
+ * amplifier gain index. Unsigned 32 bit number containing
+ * bits for all 32 antennas.
+ * @QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_ETYPE1: Bit 1 of edge
+ * amplifier gain index. Unsigned 32 bit number containing
+ * bits for all 32 antennas.
+ * @QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_ETYPE2: Bit 2 of edge
+ * amplifier gain index. Unsigned 32 bit number containing
+ * bits for all 32 antennas.
+ * @QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_PSH_HI: Phase values
+ * for first 16 antennas, 2 bits per antenna.
+ * @QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_PSH_LO: Phase values
+ * for last 16 antennas, 2 bits per antenna.
+ * @QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_DTYPE_X16: Contains
+ * DTYPE values (3 bits) for each distribution amplifier, followed
+ * by X16 switch bits for each distribution amplifier. There are
+ * total of 8 distribution amplifiers.
+ */
+enum qca_wlan_vendor_attr_dmg_rf_sector_cfg {
+ QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_MODULE_INDEX = 1,
+ QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_ETYPE0 = 2,
+ QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_ETYPE1 = 3,
+ QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_ETYPE2 = 4,
+ QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_PSH_HI = 5,
+ QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_PSH_LO = 6,
+ QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_DTYPE_X16 = 7,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_MAX =
+ QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_AFTER_LAST - 1
+};
+
+enum qca_wlan_vendor_attr_ll_stats_set {
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_INVALID = 0,
+ /* Unsigned 32-bit value */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_MPDU_SIZE_THRESHOLD = 1,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_AGGRESSIVE_STATS_GATHERING = 2,
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_MAX =
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_AFTER_LAST - 1,
+};
+
+enum qca_wlan_vendor_attr_ll_stats_clr {
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_INVALID = 0,
+ /* Unsigned 32bit bitmap for clearing statistics
+ * All radio statistics 0x00000001
+ * cca_busy_time (within radio statistics) 0x00000002
+ * All channel stats (within radio statistics) 0x00000004
+ * All scan statistics (within radio statistics) 0x00000008
+ * All interface statistics 0x00000010
+ * All tx rate statistics (within interface statistics) 0x00000020
+ * All ac statistics (with in interface statistics) 0x00000040
+ * All contention (min, max, avg) statistics (within ac statisctics)
+ * 0x00000080.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_REQ_MASK = 1,
+ /* Unsigned 8 bit value: Request to stop statistics collection */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_REQ = 2,
+
+ /* Unsigned 32 bit bitmap: Response from the driver
+ * for the cleared statistics
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK = 3,
+ /* Unsigned 8 bit value: Response from driver/firmware
+ * for the stop request
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP = 4,
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX =
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_AFTER_LAST - 1,
+};
+
+enum qca_wlan_vendor_attr_ll_stats_get {
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_INVALID = 0,
+ /* Unsigned 32 bit value provided by the caller issuing the GET stats
+ * command. When reporting the stats results, the driver uses the same
+ * value to indicate which GET request the results correspond to.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_ID = 1,
+ /* Unsigned 32 bit value - bit mask to identify what statistics are
+ * requested for retrieval.
+ * Radio Statistics 0x00000001
+ * Interface Statistics 0x00000020
+ * All Peer Statistics 0x00000040
+ * Peer Statistics 0x00000080
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK = 2,
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_MAX =
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_AFTER_LAST - 1,
+};
+
+enum qca_wlan_vendor_attr_ll_stats_results {
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_INVALID = 0,
+ /* Unsigned 32bit value. Used by the driver; must match the request id
+ * provided with the QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET command.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_RESULTS_REQ_ID = 1,
+
+ /* Unsigned 32 bit value */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_BEACON_RX = 2,
+ /* Unsigned 32 bit value */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_RX = 3,
+ /* Unsigned 32 bit value */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_RX = 4,
+ /* Unsigned 32 bit value */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_TX = 5,
+ /* Signed 32 bit value */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_MGMT = 6,
+ /* Signed 32 bit value */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_DATA = 7,
+ /* Signed 32 bit value */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_ACK = 8,
+
+ /* Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_* are
+ * nested within the interface stats.
+ */
+
+ /* Interface mode, e.g., STA, SOFTAP, IBSS, etc.
+ * Type = enum wifi_interface_mode.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MODE = 9,
+ /* Interface MAC address. An array of 6 Unsigned int8 */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MAC_ADDR = 10,
+ /* Type = enum wifi_connection_state, e.g., DISCONNECTED,
+ * AUTHENTICATING, etc. valid for STA, CLI only.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_STATE = 11,
+ /* Type = enum wifi_roam_state. Roaming state, e.g., IDLE or ACTIVE
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_ROAMING = 12,
+ /* Unsigned 32 bit value. WIFI_CAPABILITY_XXX */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_CAPABILITIES = 13,
+ /* NULL terminated SSID. An array of 33 Unsigned 8bit values */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_SSID = 14,
+ /* BSSID. An array of 6 unsigned 8 bit values */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_BSSID = 15,
+ /* Country string advertised by AP. An array of 3 unsigned 8 bit
+ * values.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_AP_COUNTRY_STR = 16,
+ /* Country string for this association. An array of 3 unsigned 8 bit
+ * values.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_COUNTRY_STR = 17,
+
+ /* Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_* could
+ * be nested within the interface stats.
+ */
+
+ /* Type = enum wifi_traffic_ac, e.g., V0, VI, BE and BK */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_AC = 18,
+ /* Unsigned int 32 value corresponding to respective AC */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MPDU = 19,
+ /* Unsigned int 32 value corresponding to respective AC */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MPDU = 20,
+ /* Unsigned int 32 value corresponding to respective AC */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MCAST = 21,
+ /* Unsigned int 32 value corresponding to respective AC */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MCAST = 22,
+ /* Unsigned int 32 value corresponding to respective AC */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_AMPDU = 23,
+ /* Unsigned int 32 value corresponding to respective AC */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_AMPDU = 24,
+ /* Unsigned int 32 value corresponding to respective AC */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_MPDU_LOST = 25,
+ /* Unsigned int 32 value corresponding to respective AC */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES = 26,
+ /* Unsigned int 32 value corresponding to respective AC */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_SHORT = 27,
+ /* Unsigned int 32 values corresponding to respective AC */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_LONG = 28,
+ /* Unsigned int 32 values corresponding to respective AC */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MIN = 29,
+ /* Unsigned int 32 values corresponding to respective AC */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MAX = 30,
+ /* Unsigned int 32 values corresponding to respective AC */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_AVG = 31,
+ /* Unsigned int 32 values corresponding to respective AC */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_NUM_SAMPLES = 32,
+ /* Unsigned 32 bit value. Number of peers */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS = 33,
+
+ /* Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_* are
+ * nested within the interface stats.
+ */
+
+ /* Type = enum wifi_peer_type. Peer type, e.g., STA, AP, P2P GO etc. */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_TYPE = 34,
+ /* MAC addr corresponding to respective peer. An array of 6 unsigned
+ * 8 bit values.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_MAC_ADDRESS = 35,
+ /* Unsigned int 32 bit value representing capabilities corresponding
+ * to respective peer.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_CAPABILITIES = 36,
+ /* Unsigned 32 bit value. Number of rates */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES = 37,
+
+ /* Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_*
+ * are nested within the rate stat.
+ */
+
+ /* Wi-Fi Rate - separate attributes defined for individual fields */
+
+ /* Unsigned int 8 bit value; 0: OFDM, 1:CCK, 2:HT 3:VHT 4..7 reserved */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_PREAMBLE = 38,
+ /* Unsigned int 8 bit value; 0:1x1, 1:2x2, 3:3x3, 4:4x4 */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_NSS = 39,
+ /* Unsigned int 8 bit value; 0:20 MHz, 1:40 MHz, 2:80 MHz, 3:160 MHz */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BW = 40,
+ /* Unsigned int 8 bit value; OFDM/CCK rate code would be as per IEEE Std
+ * in the units of 0.5 Mbps HT/VHT it would be MCS index
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MCS_INDEX = 41,
+
+ /* Unsigned 32 bit value. Bit rate in units of 100 kbps */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BIT_RATE = 42,
+
+ /* Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_STAT_* could be
+ * nested within the peer info stats.
+ */
+
+ /* Unsigned int 32 bit value. Number of successfully transmitted data
+ * packets, i.e., with ACK received corresponding to the respective
+ * rate.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_TX_MPDU = 43,
+ /* Unsigned int 32 bit value. Number of received data packets
+ * corresponding to the respective rate.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RX_MPDU = 44,
+ /* Unsigned int 32 bit value. Number of data packet losses, i.e., no ACK
+ * received corresponding to the respective rate.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MPDU_LOST = 45,
+ /* Unsigned int 32 bit value. Total number of data packet retries for
+ * the respective rate.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES = 46,
+ /* Unsigned int 32 bit value. Total number of short data packet retries
+ * for the respective rate.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_SHORT = 47,
+ /* Unsigned int 32 bit value. Total number of long data packet retries
+ * for the respective rate.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_LONG = 48,
+
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ID = 49,
+ /* Unsigned 32 bit value. Total number of msecs the radio is awake
+ * accruing over time.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME = 50,
+ /* Unsigned 32 bit value. Total number of msecs the radio is
+ * transmitting accruing over time.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME = 51,
+ /* Unsigned 32 bit value. Total number of msecs the radio is in active
+ * receive accruing over time.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_RX_TIME = 52,
+ /* Unsigned 32 bit value. Total number of msecs the radio is awake due
+ * to all scan accruing over time.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_SCAN = 53,
+ /* Unsigned 32 bit value. Total number of msecs the radio is awake due
+ * to NAN accruing over time.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_NBD = 54,
+ /* Unsigned 32 bit value. Total number of msecs the radio is awake due
+ * to GSCAN accruing over time.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_GSCAN = 55,
+ /* Unsigned 32 bit value. Total number of msecs the radio is awake due
+ * to roam scan accruing over time.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_ROAM_SCAN = 56,
+ /* Unsigned 32 bit value. Total number of msecs the radio is awake due
+ * to PNO scan accruing over time.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_PNO_SCAN = 57,
+ /* Unsigned 32 bit value. Total number of msecs the radio is awake due
+ * to Hotspot 2.0 scans and GAS exchange accruing over time.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_HS20 = 58,
+ /* Unsigned 32 bit value. Number of channels. */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS = 59,
+
+ /* Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_* could
+ * be nested within the channel stats.
+ */
+
+ /* Type = enum wifi_channel_width. Channel width, e.g., 20, 40, 80 */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_WIDTH = 60,
+ /* Unsigned 32 bit value. Primary 20 MHz channel. */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ = 61,
+ /* Unsigned 32 bit value. Center frequency (MHz) first segment. */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ0 = 62,
+ /* Unsigned 32 bit value. Center frequency (MHz) second segment. */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ1 = 63,
+
+ /* Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_* could be
+ * nested within the radio stats.
+ */
+
+ /* Unsigned int 32 bit value representing total number of msecs the
+ * radio is awake on that channel accruing over time, corresponding to
+ * the respective channel.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_ON_TIME = 64,
+ /* Unsigned int 32 bit value representing total number of msecs the CCA
+ * register is busy accruing over time corresponding to the respective
+ * channel.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_CCA_BUSY_TIME = 65,
+
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_NUM_RADIOS = 66,
+
+ /* Signifies the nested list of channel attributes
+ * QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_*
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO = 67,
+
+ /* Signifies the nested list of peer info attributes
+ * QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_*
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO = 68,
+
+ /* Signifies the nested list of rate info attributes
+ * QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_*
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_RATE_INFO = 69,
+
+ /* Signifies the nested list of wmm info attributes
+ * QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_*
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_INFO = 70,
+
+ /* Unsigned 8 bit value. Used by the driver; if set to 1, it indicates
+ * that more stats, e.g., peers or radio, are to follow in the next
+ * QCA_NL80211_VENDOR_SUBCMD_LL_STATS_*_RESULTS event.
+ * Otherwise, it is set to 0.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_RESULTS_MORE_DATA = 71,
+
+ /* Unsigned 64 bit value */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_AVERAGE_TSF_OFFSET = 72,
+
+ /* Unsigned 32 bit value */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_DETECTED = 73,
+
+ /* Unsigned 32 bit value */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_AVG_NUM_FRAMES_LEAKED = 74,
+
+ /* Unsigned 32 bit value */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_GUARD_TIME = 75,
+
+ /* Unsigned 32 bit value */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE = 76,
+
+ /* Unsigned 32 bit value */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_TX_LEVELS = 77,
+
+ /* Number of msecs the radio spent in transmitting for each power level
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME_PER_LEVEL = 78,
+
+ /* Unsigned 32 bit value */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RTS_SUCC_CNT = 79,
+ /* Unsigned 32 bit value */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RTS_FAIL_CNT = 80,
+ /* Unsigned 32 bit value */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_PPDU_SUCC_CNT = 81,
+ /* Unsigned 32 bit value */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_PPDU_FAIL_CNT = 82,
+
+ /* Unsigned int 32 value.
+ * Pending MSDUs corresponding to respective AC.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_PENDING_MSDU = 83,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX =
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_AFTER_LAST - 1,
+};
+
+enum qca_wlan_vendor_attr_ll_stats_type {
+ QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_INVALID = 0,
+ QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_RADIO = 1,
+ QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_IFACE = 2,
+ QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_PEERS = 3,
+
+ /* keep last */
+ QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_AFTER_LAST,
+ QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_MAX =
+ QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_tdls_configuration - Attributes for
+ * TDLS configuration to the host driver.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TRIGGER_MODE: Configure the TDLS trigger
+ * mode in the host driver. enum qca_wlan_vendor_tdls_trigger_mode
+ * represents the different TDLS trigger modes.
+ * @QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TX_STATS_PERIOD: Duration (u32) within
+ * which QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TX_THRESHOLD number
+ * of packets shall meet the criteria for implicit TDLS setup.
+ * @QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TX_THRESHOLD: Number (u32) of Tx/Rx packets
+ * within a duration QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TX_STATS_PERIOD
+ * to initiate a TDLS setup.
+ * @QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_DISCOVERY_PERIOD: Time (u32) to initiate
+ * a TDLS Discovery to the peer.
+ * @QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_MAX_DISCOVERY_ATTEMPT: Max number (u32) of
+ * discovery attempts to know the TDLS capability of the peer. A peer is
+ * marked as TDLS not capable if there is no response for all the attempts.
+ * @QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_IDLE_TIMEOUT: Represents a duration (u32)
+ * within which QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_IDLE_PACKET_THRESHOLD
+ * number of TX / RX frames meet the criteria for TDLS teardown.
+ * @QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_IDLE_PACKET_THRESHOLD: Minimum number (u32)
+ * of Tx/Rx packets within a duration
+ * QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_IDLE_TIMEOUT to tear down a TDLS link.
+ * @QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_SETUP_RSSI_THRESHOLD: Threshold
+ * corresponding to the RSSI of the peer below which a TDLS setup is
+ * triggered.
+ * @QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TEARDOWN_RSSI_THRESHOLD: Threshold
+ * corresponding to the RSSI of the peer above which a TDLS teardown is
+ * triggered.
+ */
+enum qca_wlan_vendor_attr_tdls_configuration {
+ QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TRIGGER_MODE = 1,
+
+ /* Attributes configuring the TDLS Implicit Trigger */
+ QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TX_STATS_PERIOD = 2,
+ QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TX_THRESHOLD = 3,
+ QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_DISCOVERY_PERIOD = 4,
+ QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_MAX_DISCOVERY_ATTEMPT = 5,
+ QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_IDLE_TIMEOUT = 6,
+ QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_IDLE_PACKET_THRESHOLD = 7,
+ QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_SETUP_RSSI_THRESHOLD = 8,
+ QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TEARDOWN_RSSI_THRESHOLD = 9,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_MAX =
+ QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_AFTER_LAST - 1
+};
+
+/**
+ * enum qca_wlan_vendor_tdls_trigger_mode: Represents the TDLS trigger mode in
+ * the driver
+ *
+ * The following are the different values for
+ * QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TRIGGER_MODE.
+ *
+ * @QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_EXPLICIT: The trigger to initiate/teardown
+ * the TDLS connection to a respective peer comes from the user space.
+ * wpa_supplicant provides the commands TDLS_SETUP, TDLS_TEARDOWN,
+ * TDLS_DISCOVER to do this.
+ * @QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_IMPLICIT: Host driver triggers this TDLS
+ * setup/teardown to the eligible peer once the configured criteria
+ * (such as TX/RX threshold, RSSI) is met. The attributes
+ * in QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_IMPLICIT_PARAMS correspond to
+ * the different configuration criteria for the TDLS trigger from the
+ * host driver.
+ * @QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_EXTERNAL: Enables the driver to trigger
+ * the TDLS setup / teardown through the implicit mode only to the
+ * configured MAC addresses (wpa_supplicant, with tdls_external_control=1,
+ * configures the MAC address through TDLS_SETUP / TDLS_TEARDOWN commands).
+ * External mode works on top of the implicit mode. Thus the host driver
+ * is expected to configure in TDLS Implicit mode too to operate in
+ * External mode.
+ * Configuring External mode alone without Implicit mode is invalid.
+ *
+ * All the above implementations work as expected only when the host driver
+ * advertises the capability WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP - representing
+ * that the TDLS message exchange is not internal to the host driver, but
+ * depends on wpa_supplicant to do the message exchange.
+ */
+enum qca_wlan_vendor_tdls_trigger_mode {
+ QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_EXPLICIT = 1 << 0,
+ QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_IMPLICIT = 1 << 1,
+ QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_EXTERNAL = 1 << 2,
+};
+
+/**
+ * enum qca_vendor_attr_sar_limits_selections - Source of SAR power limits
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0: Select SAR profile #0
+ * that is hard-coded in the Board Data File (BDF).
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1: Select SAR profile #1
+ * that is hard-coded in the Board Data File (BDF).
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2: Select SAR profile #2
+ * that is hard-coded in the Board Data File (BDF).
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3: Select SAR profile #3
+ * that is hard-coded in the Board Data File (BDF).
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4: Select SAR profile #4
+ * that is hard-coded in the Board Data File (BDF).
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE: Do not select any
+ * source of SAR power limits, thereby disabling the SAR power
+ * limit feature.
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER: Select the SAR power
+ * limits configured by %QCA_NL80211_VENDOR_SUBCMD_SET_SAR.
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_V2_0: Select the SAR power
+ * limits version 2.0 configured by %QCA_NL80211_VENDOR_SUBCMD_SET_SAR.
+ *
+ * This enumerates the valid set of values that may be supplied for
+ * attribute %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT in an instance of
+ * the %QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS vendor command or in
+ * the response to an instance of the
+ * %QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS vendor command.
+ */
+enum qca_vendor_attr_sar_limits_selections {
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0 = 0,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1 = 1,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2 = 2,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3 = 3,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4 = 4,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE = 5,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER = 6,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_V2_0 = 7,
+};
+
+/**
+ * enum qca_vendor_attr_sar_limits_spec_modulations -
+ * SAR limits specification modulation
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK -
+ * CCK modulation
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM -
+ * OFDM modulation
+ *
+ * This enumerates the valid set of values that may be supplied for
+ * attribute %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION in an
+ * instance of attribute %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC in an
+ * instance of the %QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS vendor
+ * command or in the response to an instance of the
+ * %QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS vendor command.
+ */
+enum qca_vendor_attr_sar_limits_spec_modulations {
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK = 0,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM = 1,
+};
+
+/**
+ * enum qca_vendor_attr_sar_limits - Attributes for SAR power limits
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE: Optional (u32) value to
+ * select which SAR power limit table should be used. Valid
+ * values are enumerated in enum
+ * %qca_vendor_attr_sar_limits_selections. The existing SAR
+ * power limit selection is unchanged if this attribute is not
+ * present.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS: Optional (u32) value
+ * which specifies the number of SAR power limit specifications
+ * which will follow.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC: Nested array of SAR power
+ * limit specifications. The number of specifications is
+ * specified by @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS. Each
+ * specification contains a set of
+ * QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_* attributes. A
+ * specification is uniquely identified by the attributes
+ * %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND,
+ * %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN, and
+ * %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION and always
+ * contains as a payload the attribute
+ * %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT,
+ * %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT_INDEX.
+ * Either %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT or
+ * %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT_INDEX is
+ * needed based upon the value of
+ * %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND: Optional (u32) value to
+ * indicate for which band this specification applies. Valid
+ * values are enumerated in enum %nl80211_band (although not all
+ * bands may be supported by a given device). If the attribute is
+ * not supplied then the specification will be applied to all
+ * supported bands.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN: Optional (u32) value
+ * to indicate for which antenna chain this specification
+ * applies, i.e. 1 for chain 1, 2 for chain 2, etc. If the
+ * attribute is not supplied then the specification will be
+ * applied to all chains.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION: Optional (u32)
+ * value to indicate for which modulation scheme this
+ * specification applies. Valid values are enumerated in enum
+ * %qca_vendor_attr_sar_limits_spec_modulations. If the attribute
+ * is not supplied then the specification will be applied to all
+ * modulation schemes.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT: Required (u32)
+ * value to specify the actual power limit value in units of 0.5
+ * dBm (i.e., a value of 11 represents 5.5 dBm).
+ * This is required, when %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT is
+ * %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT_INDEX: Required (u32)
+ * value to indicate SAR V2 indices (0 - 11) to select SAR V2 profiles.
+ * This is required, when %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT is
+ * %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_V2_0.
+ *
+ * These attributes are used with %QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS
+ * and %QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS.
+ */
+enum qca_vendor_attr_sar_limits {
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE = 1,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS = 2,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC = 3,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND = 4,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN = 5,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION = 6,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT = 7,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT_INDEX = 8,
+
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX =
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_AFTER_LAST - 1
+};
+
+/**
+ * enum qca_wlan_vendor_attr_get_wifi_info: Attributes for data used by
+ * QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO sub command.
+ */
+enum qca_wlan_vendor_attr_get_wifi_info {
+ QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION = 1,
+ QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION = 2,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX =
+ QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_AFTER_LAST - 1,
+};
+
+/*
+ * enum qca_wlan_vendor_attr_wifi_logger_start: Attributes for data used by
+ * QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START sub command.
+ */
+enum qca_wlan_vendor_attr_wifi_logger_start {
+ QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID = 1,
+ QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL = 2,
+ QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS = 3,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_GET_MAX =
+ QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_AFTER_LAST - 1,
+};
+
+enum qca_wlan_vendor_attr_logger_results {
+ QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_INVALID = 0,
+
+ /* Unsigned 32-bit value; must match the request Id supplied by
+ * Wi-Fi HAL in the corresponding subcmd NL msg.
+ */
+ QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_REQUEST_ID = 1,
+
+ /* Unsigned 32-bit value; used to indicate the size of memory
+ * dump to be allocated.
+ */
+ QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_MEMDUMP_SIZE = 2,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_MAX =
+ QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_AFTER_LAST - 1,
+};
+
+enum qca_wlan_vendor_attr_roaming_config_params {
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_INVALID = 0,
+
+ QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD = 1,
+ QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID = 2,
+
+ /* Attributes for wifi_set_ssid_white_list */
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS = 3,
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST = 4,
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID = 5,
+
+ /* Attributes for set_roam_params */
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD = 6,
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD = 7,
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR = 8,
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR = 9,
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST = 10,
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS = 11,
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER = 12,
+
+ /* Attribute for set_lazy_roam */
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE = 13,
+
+ /* Attribute for set_lazy_roam with preferences */
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS = 14,
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID = 15,
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID = 16,
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER = 17,
+
+ /* Attribute for set_blacklist bssid params */
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS = 18,
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID = 19,
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID = 20,
+ /* Flag attribute indicates this BSSID blacklist as a hint */
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_HINT = 21,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX =
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_AFTER_LAST - 1,
+};
+
+/*
+ * enum qca_wlan_vendor_attr_roam_subcmd: Attributes for data used by
+ * QCA_NL80211_VENDOR_SUBCMD_ROAM sub command.
+ */
+enum qca_wlan_vendor_attr_roam_subcmd {
+ QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST = 1,
+ QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_GSCAN_ROAM_PARAMS = 2,
+ QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM = 3,
+ QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS = 4,
+ QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PARAMS = 5,
+ QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID = 6,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX =
+ QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_AFTER_LAST - 1,
+};
+
+enum qca_wlan_vendor_attr_gscan_config_params {
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_INVALID = 0,
+
+ /* Unsigned 32-bit value */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID = 1,
+
+ /* Attributes for data used by
+ * QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_VALID_CHANNELS sub command.
+ */
+ /* Unsigned 32-bit value */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND
+ = 2,
+ /* Unsigned 32-bit value */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS
+ = 3,
+
+ /* Attributes for input params used by
+ * QCA_NL80211_VENDOR_SUBCMD_GSCAN_START sub command.
+ */
+
+ /* Unsigned 32-bit value; channel frequency */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC_CHANNEL = 4,
+ /* Unsigned 32-bit value; dwell time in ms. */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC_DWELL_TIME = 5,
+ /* Unsigned 8-bit value; 0: active; 1: passive; N/A for DFS */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC_PASSIVE = 6,
+ /* Unsigned 8-bit value; channel class */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC_CLASS = 7,
+
+ /* Unsigned 8-bit value; bucket index, 0 based */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_INDEX = 8,
+ /* Unsigned 8-bit value; band. */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_BAND = 9,
+ /* Unsigned 32-bit value; desired period, in ms. */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_PERIOD = 10,
+ /* Unsigned 8-bit value; report events semantics. */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_REPORT_EVENTS = 11,
+ /* Unsigned 32-bit value. Followed by a nested array of
+ * GSCAN_CHANNEL_SPEC_* attributes.
+ */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS = 12,
+
+ /* Array of QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC_* attributes.
+ * Array size: QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS
+ */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC = 13,
+
+ /* Unsigned 32-bit value; base timer period in ms. */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_BASE_PERIOD = 14,
+ /* Unsigned 32-bit value; number of APs to store in each scan in the
+ * BSSID/RSSI history buffer (keep the highest RSSI APs).
+ */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_MAX_AP_PER_SCAN = 15,
+ /* Unsigned 8-bit value; in %, when scan buffer is this much full, wake
+ * up AP.
+ */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_PERCENT
+ = 16,
+
+ /* Unsigned 8-bit value; number of scan bucket specs; followed by a
+ * nested array of_GSCAN_BUCKET_SPEC_* attributes and values. The size
+ * of the array is determined by NUM_BUCKETS.
+ */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS = 17,
+
+ /* Array of QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_* attributes.
+ * Array size: QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS
+ */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC = 18,
+
+ /* Unsigned 8-bit value */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH
+ = 19,
+ /* Unsigned 32-bit value; maximum number of results to be returned. */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_MAX
+ = 20,
+
+ /* An array of 6 x unsigned 8-bit value */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_BSSID = 21,
+ /* Signed 32-bit value */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_RSSI_LOW = 22,
+ /* Signed 32-bit value */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH = 23,
+ /* Unsigned 32-bit value */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_CHANNEL = 24,
+
+ /* Number of hotlist APs as unsigned 32-bit value, followed by a nested
+ * array of AP_THRESHOLD_PARAM attributes and values. The size of the
+ * array is determined by NUM_AP.
+ */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_BSSID_HOTLIST_PARAMS_NUM_AP = 25,
+
+ /* Array of QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_* attributes.
+ * Array size: QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS
+ */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM = 26,
+
+ /* Unsigned 32-bit value; number of samples for averaging RSSI. */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE
+ = 27,
+ /* Unsigned 32-bit value; number of samples to confirm AP loss. */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE
+ = 28,
+ /* Unsigned 32-bit value; number of APs breaching threshold. */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING = 29,
+ /* Unsigned 32-bit value; number of APs. Followed by an array of
+ * AP_THRESHOLD_PARAM attributes. Size of the array is NUM_AP.
+ */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP = 30,
+ /* Unsigned 32-bit value; number of samples to confirm AP loss. */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE
+ = 31,
+ /* Unsigned 32-bit value. If max_period is non zero or different than
+ * period, then this bucket is an exponential backoff bucket.
+ */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_MAX_PERIOD = 32,
+ /* Unsigned 32-bit value. */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_BASE = 33,
+ /* Unsigned 32-bit value. For exponential back off bucket, number of
+ * scans to perform for a given period.
+ */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_STEP_COUNT = 34,
+ /* Unsigned 8-bit value; in number of scans, wake up AP after these
+ * many scans.
+ */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_NUM_SCANS
+ = 35,
+
+ /* Attributes for data used by
+ * QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_SSID_HOTLIST sub command.
+ */
+ /* Unsigned 3-2bit value; number of samples to confirm SSID loss. */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_HOTLIST_PARAMS_LOST_SSID_SAMPLE_SIZE
+ = 36,
+ /* Number of hotlist SSIDs as unsigned 32-bit value, followed by a
+ * nested array of SSID_THRESHOLD_PARAM_* attributes and values. The
+ * size of the array is determined by NUM_SSID.
+ */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_HOTLIST_PARAMS_NUM_SSID = 37,
+ /* Array of QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_THRESHOLD_PARAM_*
+ * attributes.
+ * Array size: QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_HOTLIST_PARAMS_NUM_SSID
+ */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_THRESHOLD_PARAM = 38,
+
+ /* An array of 33 x unsigned 8-bit value; NULL terminated SSID */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_THRESHOLD_PARAM_SSID = 39,
+ /* Unsigned 8-bit value */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_THRESHOLD_PARAM_BAND = 40,
+ /* Signed 32-bit value */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_THRESHOLD_PARAM_RSSI_LOW = 41,
+ /* Signed 32-bit value */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_THRESHOLD_PARAM_RSSI_HIGH = 42,
+ /* Unsigned 32-bit value; a bitmask with additional gscan config flag.
+ */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_CONFIGURATION_FLAGS = 43,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_MAX =
+ QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_AFTER_LAST - 1,
+};
+
+enum qca_wlan_vendor_attr_gscan_results {
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_INVALID = 0,
+
+ /* Unsigned 32-bit value; must match the request Id supplied by
+ * Wi-Fi HAL in the corresponding subcmd NL msg.
+ */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID = 1,
+
+ /* Unsigned 32-bit value; used to indicate the status response from
+ * firmware/driver for the vendor sub-command.
+ */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_STATUS = 2,
+
+ /* GSCAN Valid Channels attributes */
+ /* Unsigned 32bit value; followed by a nested array of CHANNELS. */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_CHANNELS = 3,
+ /* An array of NUM_CHANNELS x unsigned 32-bit value integers
+ * representing channel numbers.
+ */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CHANNELS = 4,
+
+ /* GSCAN Capabilities attributes */
+ /* Unsigned 32-bit value */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE = 5,
+ /* Unsigned 32-bit value */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS = 6,
+ /* Unsigned 32-bit value */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN
+ = 7,
+ /* Unsigned 32-bit value */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE
+ = 8,
+ /* Signed 32-bit value */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD
+ = 9,
+ /* Unsigned 32-bit value */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS = 10,
+ /* Unsigned 32-bit value */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS
+ = 11,
+ /* Unsigned 32-bit value */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES
+ = 12,
+
+ /* GSCAN Attributes used with
+ * QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_RESULTS_AVAILABLE sub-command.
+ */
+
+ /* Unsigned 32-bit value */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE = 13,
+
+ /* GSCAN attributes used with
+ * QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT sub-command.
+ */
+
+ /* An array of NUM_RESULTS_AVAILABLE x
+ * QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_*
+ */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST = 14,
+
+ /* Unsigned 64-bit value; age of sample at the time of retrieval */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP = 15,
+ /* 33 x unsigned 8-bit value; NULL terminated SSID */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID = 16,
+ /* An array of 6 x unsigned 8-bit value */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID = 17,
+ /* Unsigned 32-bit value; channel frequency in MHz */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL = 18,
+ /* Signed 32-bit value */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI = 19,
+ /* Unsigned 32-bit value */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT = 20,
+ /* Unsigned 32-bit value */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD = 21,
+ /* Unsigned 16-bit value */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD = 22,
+ /* Unsigned 16-bit value */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CAPABILITY = 23,
+ /* Unsigned 32-bit value; size of the IE DATA blob */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_IE_LENGTH = 24,
+ /* An array of IE_LENGTH x unsigned 8-bit value; blob of all the
+ * information elements found in the beacon; this data should be a
+ * packed list of wifi_information_element objects, one after the
+ * other.
+ */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_IE_DATA = 25,
+
+ /* Unsigned 8-bit value; set by driver to indicate more scan results are
+ * available.
+ */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA = 26,
+
+ /* GSCAN attributes for
+ * QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_EVENT sub-command.
+ */
+ /* Unsigned 8-bit value */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_EVENT_TYPE = 27,
+ /* Unsigned 32-bit value */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_EVENT_STATUS = 28,
+
+ /* GSCAN attributes for
+ * QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_FOUND sub-command.
+ */
+ /* Use attr QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE
+ * to indicate number of results.
+ * Also, use QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST to indicate the
+ * list of results.
+ */
+
+ /* GSCAN attributes for
+ * QCA_NL80211_VENDOR_SUBCMD_GSCAN_SIGNIFICANT_CHANGE sub-command.
+ */
+ /* An array of 6 x unsigned 8-bit value */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_BSSID = 29,
+ /* Unsigned 32-bit value */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_CHANNEL
+ = 30,
+ /* Unsigned 32-bit value. */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_NUM_RSSI
+ = 31,
+ /* A nested array of signed 32-bit RSSI values. Size of the array is
+ * determined by (NUM_RSSI of SIGNIFICANT_CHANGE_RESULT_NUM_RSSI.
+ */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_RSSI_LIST
+ = 32,
+
+ /* GSCAN attributes used with
+ * QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CACHED_RESULTS sub-command.
+ */
+ /* Use attr QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE
+ * to indicate number of gscan cached results returned.
+ * Also, use QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_LIST to indicate
+ * the list of gscan cached results.
+ */
+
+ /* An array of NUM_RESULTS_AVAILABLE x
+ * QCA_NL80211_VENDOR_ATTR_GSCAN_CACHED_RESULTS_*
+ */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_LIST = 33,
+ /* Unsigned 32-bit value; a unique identifier for the scan unit. */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_SCAN_ID = 34,
+ /* Unsigned 32-bit value; a bitmask w/additional information about scan.
+ */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_FLAGS = 35,
+ /* Use attr QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE
+ * to indicate number of wifi scan results/bssids retrieved by the scan.
+ * Also, use QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST to indicate the
+ * list of wifi scan results returned for each cached result block.
+ */
+
+ /* GSCAN attributes for
+ * QCA_NL80211_VENDOR_SUBCMD_PNO_NETWORK_FOUND sub-command.
+ */
+ /* Use QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE for
+ * number of results.
+ * Use QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST to indicate the nested
+ * list of wifi scan results returned for each
+ * wifi_passpoint_match_result block.
+ * Array size: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE.
+ */
+
+ /* GSCAN attributes for
+ * QCA_NL80211_VENDOR_SUBCMD_PNO_PASSPOINT_NETWORK_FOUND sub-command.
+ */
+ /* Unsigned 32-bit value */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_NETWORK_FOUND_NUM_MATCHES
+ = 36,
+ /* A nested array of
+ * QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_MATCH_*
+ * attributes. Array size =
+ * *_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_NETWORK_FOUND_NUM_MATCHES.
+ */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_MATCH_RESULT_LIST = 37,
+
+ /* Unsigned 32-bit value; network block id for the matched network */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_MATCH_ID = 38,
+ /* Use QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST to indicate the nested
+ * list of wifi scan results returned for each
+ * wifi_passpoint_match_result block.
+ */
+ /* Unsigned 32-bit value */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP_LEN = 39,
+ /* An array size of PASSPOINT_MATCH_ANQP_LEN of unsigned 8-bit values;
+ * ANQP data in the information_element format.
+ */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP = 40,
+
+ /* Unsigned 32-bit value; a GSCAN Capabilities attribute. */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS = 41,
+ /* Unsigned 32-bit value; a GSCAN Capabilities attribute. */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS = 42,
+ /* Unsigned 32-bit value; a GSCAN Capabilities attribute. */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID
+ = 43,
+ /* Unsigned 32-bit value; a GSCAN Capabilities attribute. */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID
+ = 44,
+
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_BUCKETS_SCANNED = 45,
+
+ /* Unsigned 32-bit value; a GSCAN Capabilities attribute.
+ * This is used to limit the maximum number of BSSIDs while sending
+ * the vendor command QCA_NL80211_VENDOR_SUBCMD_ROAM with attributes
+ * QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID and
+ * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID.
+ */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_MAX_NUM_BLACKLISTED_BSSID = 46,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX =
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_AFTER_LAST - 1,
+};
+
+enum qca_wlan_vendor_attr_pno_config_params {
+ QCA_WLAN_VENDOR_ATTR_PNO_INVALID = 0,
+ /* Attributes for data used by
+ * QCA_NL80211_VENDOR_SUBCMD_PNO_SET_PASSPOINT_LIST sub command.
+ */
+ /* Unsigned 32-bit value */
+ QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM = 1,
+ /* Array of nested QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_*
+ * attributes. Array size =
+ * QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM.
+ */
+ QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NETWORK_ARRAY = 2,
+
+ /* Unsigned 32-bit value */
+ QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ID = 3,
+ /* An array of 256 x unsigned 8-bit value; NULL terminated UTF-8 encoded
+ * realm, 0 if unspecified.
+ */
+ QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM = 4,
+ /* An array of 16 x unsigned 32-bit value; roaming consortium ids to
+ * match, 0 if unspecified.
+ */
+ QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_CNSRTM_ID = 5,
+ /* An array of 6 x unsigned 8-bit value; MCC/MNC combination, 0s if
+ * unspecified.
+ */
+ QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_PLMN = 6,
+
+ /* Attributes for data used by
+ * QCA_NL80211_VENDOR_SUBCMD_PNO_SET_LIST sub command.
+ */
+ /* Unsigned 32-bit value */
+ QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS = 7,
+ /* Array of nested
+ * QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_*
+ * attributes. Array size =
+ * QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS.
+ */
+ QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST = 8,
+ /* An array of 33 x unsigned 8-bit value; NULL terminated SSID */
+ QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID = 9,
+ /* Signed 8-bit value; threshold for considering this SSID as found,
+ * required granularity for this threshold is 4 dBm to 8 dBm.
+ */
+ QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_RSSI_THRESHOLD
+ = 10,
+ /* Unsigned 8-bit value; WIFI_PNO_FLAG_XXX */
+ QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS = 11,
+ /* Unsigned 8-bit value; auth bit field for matching WPA IE */
+ QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT = 12,
+ /* Unsigned 8-bit to indicate ePNO type;
+ * It takes values from qca_wlan_epno_type
+ */
+ QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_TYPE = 13,
+
+ /* Nested attribute to send the channel list */
+ QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_CHANNEL_LIST = 14,
+
+ /* Unsigned 32-bit value; indicates the interval between PNO scan
+ * cycles in msec.
+ */
+ QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_SCAN_INTERVAL = 15,
+ QCA_WLAN_VENDOR_ATTR_EPNO_MIN5GHZ_RSSI = 16,
+ QCA_WLAN_VENDOR_ATTR_EPNO_MIN24GHZ_RSSI = 17,
+ QCA_WLAN_VENDOR_ATTR_EPNO_INITIAL_SCORE_MAX = 18,
+ QCA_WLAN_VENDOR_ATTR_EPNO_CURRENT_CONNECTION_BONUS = 19,
+ QCA_WLAN_VENDOR_ATTR_EPNO_SAME_NETWORK_BONUS = 20,
+ QCA_WLAN_VENDOR_ATTR_EPNO_SECURE_BONUS = 21,
+ QCA_WLAN_VENDOR_ATTR_EPNO_BAND5GHZ_BONUS = 22,
+ /* Unsigned 32-bit value, representing the PNO Request ID */
+ QCA_WLAN_VENDOR_ATTR_PNO_CONFIG_REQUEST_ID = 23,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_PNO_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_PNO_MAX =
+ QCA_WLAN_VENDOR_ATTR_PNO_AFTER_LAST - 1,
+};
+
+/**
+ * qca_wlan_vendor_acs_select_reason: This represents the different reasons why
+ * the ACS has to be triggered. These values are used by
+ * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON and
+ * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
+ */
+enum qca_wlan_vendor_acs_select_reason {
+ /* Represents the reason that the ACS triggered during the AP start */
+ QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT,
+ /* Represents the reason that DFS found with the current channel */
+ QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS,
+ /* Represents the reason that LTE co-exist in the current band. */
+ QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX,
+};
+
+/**
+ * qca_wlan_vendor_attr_external_acs_policy: Attribute values for
+ * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_POLICY to the vendor subcmd
+ * QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS. This represents the
+ * external ACS policies to select the channels w.r.t. the PCL weights.
+ * (QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL represents the channels and
+ * their PCL weights.)
+ * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_MANDATORY: Mandatory to
+ * select a channel with non-zero PCL weight.
+ * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_PREFERRED: Prefer a
+ * channel with non-zero PCL weight.
+ *
+ */
+enum qca_wlan_vendor_attr_external_acs_policy {
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_PREFERRED,
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_MANDATORY,
+};
+
+/**
+ * qca_wlan_vendor_channel_prop_flags: This represent the flags for a channel.
+ * This is used by QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS.
+ */
+enum qca_wlan_vendor_channel_prop_flags {
+ /* Bits 0, 1, 2, and 3 are reserved */
+
+ /* Turbo channel */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_TURBO = 1 << 4,
+ /* CCK channel */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_CCK = 1 << 5,
+ /* OFDM channel */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_OFDM = 1 << 6,
+ /* 2.4 GHz spectrum channel. */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_2GHZ = 1 << 7,
+ /* 5 GHz spectrum channel */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_5GHZ = 1 << 8,
+ /* Only passive scan allowed */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_PASSIVE = 1 << 9,
+ /* Dynamic CCK-OFDM channel */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_DYN = 1 << 10,
+ /* GFSK channel (FHSS PHY) */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_GFSK = 1 << 11,
+ /* Radar found on channel */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_RADAR = 1 << 12,
+ /* 11a static turbo channel only */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_STURBO = 1 << 13,
+ /* Half rate channel */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HALF = 1 << 14,
+ /* Quarter rate channel */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_QUARTER = 1 << 15,
+ /* HT 20 channel */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HT20 = 1 << 16,
+ /* HT 40 with extension channel above */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HT40PLUS = 1 << 17,
+ /* HT 40 with extension channel below */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HT40MINUS = 1 << 18,
+ /* HT 40 intolerant */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HT40INTOL = 1 << 19,
+ /* VHT 20 channel */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_VHT20 = 1 << 20,
+ /* VHT 40 with extension channel above */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_VHT40PLUS = 1 << 21,
+ /* VHT 40 with extension channel below */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_VHT40MINUS = 1 << 22,
+ /* VHT 80 channel */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_VHT80 = 1 << 23,
+ /* HT 40 intolerant mark bit for ACS use */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HT40INTOLMARK = 1 << 24,
+ /* Channel temporarily blocked due to noise */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_BLOCKED = 1 << 25,
+ /* VHT 160 channel */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_VHT160 = 1 << 26,
+ /* VHT 80+80 channel */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_VHT80_80 = 1 << 27,
+ /* HE 20 channel */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HE20 = 1 << 28,
+ /* HE 40 with extension channel above */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HE40PLUS = 1 << 29,
+ /* HE 40 with extension channel below */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HE40MINUS = 1 << 30,
+ /* HE 40 intolerant */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HE40INTOL = 1 << 31,
+};
+
+/**
+ * qca_wlan_vendor_channel_prop_flags_2: This represents the flags for a
+ * channel, and is a continuation of qca_wlan_vendor_channel_prop_flags. This is
+ * used by QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS_2.
+ */
+enum qca_wlan_vendor_channel_prop_flags_2 {
+ /* HE 40 intolerant mark bit for ACS use */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HE40INTOLMARK = 1 << 0,
+ /* HE 80 channel */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HE80 = 1 << 1,
+ /* HE 160 channel */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HE160 = 1 << 2,
+ /* HE 80+80 channel */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HE80_80 = 1 << 3,
+};
+
+/**
+ * qca_wlan_vendor_channel_prop_flags_ext: This represent the extended flags for
+ * each channel. This is used by
+ * QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT.
+ */
+enum qca_wlan_vendor_channel_prop_flags_ext {
+ /* Radar found on channel */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_RADAR_FOUND = 1 << 0,
+ /* DFS required on channel */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_DFS = 1 << 1,
+ /* DFS required on channel for 2nd band of 80+80 */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_DFS_CFREQ2 = 1 << 2,
+ /* If channel has been checked for DFS */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_DFS_CLEAR = 1 << 3,
+ /* Excluded in 802.11d */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_11D_EXCLUDED = 1 << 4,
+ /* Channel Switch Announcement received on this channel */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_CSA_RECEIVED = 1 << 5,
+ /* Ad-hoc is not allowed */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_DISALLOW_ADHOC = 1 << 6,
+ /* Station only channel */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_DISALLOW_HOSTAP = 1 << 7,
+ /* DFS radar history for slave device (STA mode) */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_HISTORY_RADAR = 1 << 8,
+ /* DFS CAC valid for slave device (STA mode) */
+ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_CAC_VALID = 1 << 9,
+};
+
+/**
+ * qca_wlan_vendor_external_acs_event_chan_info_attr: Represents per channel
+ * information. These attributes are sent as part of
+ * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO. Each set of the following
+ * attributes correspond to a single channel.
+ */
+enum qca_wlan_vendor_external_acs_event_chan_info_attr {
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_INVALID = 0,
+
+ /* A bitmask (u32) with flags specified in
+ * enum qca_wlan_vendor_channel_prop_flags.
+ */
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS = 1,
+ /* A bitmask (u32) with flags specified in
+ * enum qca_wlan_vendor_channel_prop_flags_ext.
+ */
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT = 2,
+ /* frequency in MHz (u32) */
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ = 3,
+ /* maximum regulatory transmission power (u32) */
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER = 4,
+ /* maximum transmission power (u32) */
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER = 5,
+ /* minimum transmission power (u32) */
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER = 6,
+ /* regulatory class id (u8) */
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID = 7,
+ /* maximum antenna gain in (u8) */
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN = 8,
+ /* VHT segment 0 (u8) */
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0 = 9,
+ /* VHT segment 1 (u8) */
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1 = 10,
+ /* A bitmask (u32) with flags specified in
+ * enum qca_wlan_vendor_channel_prop_flags_2.
+ */
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS_2 = 11,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_LAST,
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX =
+ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_LAST - 1,
+};
+
+/**
+ * qca_wlan_vendor_attr_pcl: Represents attributes for
+ * preferred channel list (PCL). These attributes are sent as part of
+ * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL and
+ * QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST.
+ */
+enum qca_wlan_vendor_attr_pcl {
+ QCA_WLAN_VENDOR_ATTR_PCL_INVALID = 0,
+
+ /* Channel number (u8) */
+ QCA_WLAN_VENDOR_ATTR_PCL_CHANNEL = 1,
+ /* Channel weightage (u8) */
+ QCA_WLAN_VENDOR_ATTR_PCL_WEIGHT = 2,
+ /* Channel frequency (u32) in MHz */
+ QCA_WLAN_VENDOR_ATTR_PCL_FREQ = 3,
+ /* Channel flags (u32)
+ * bit 0 set: channel to be used for GO role,
+ * bit 1 set: channel to be used on CLI role,
+ * bit 2 set: channel must be considered for operating channel
+ * selection & peer chosen operating channel should be
+ * one of the channels with this flag set,
+ * bit 3 set: channel should be excluded in GO negotiation
+ */
+ QCA_WLAN_VENDOR_ATTR_PCL_FLAG = 4,
+};
+
+/**
+ * qca_wlan_vendor_attr_external_acs_event: Attribute to vendor sub-command
+ * QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS. This attribute will be sent by
+ * host driver.
+ */
+enum qca_wlan_vendor_attr_external_acs_event {
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_INVALID = 0,
+
+ /* This reason (u8) refers to enum qca_wlan_vendor_acs_select_reason.
+ * This helps ACS module to understand why ACS needs to be started.
+ */
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON = 1,
+ /* Flag attribute to indicate if driver supports spectral scanning */
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_SPECTRAL_SUPPORTED = 2,
+ /* Flag attribute to indicate if 11ac is offloaded to firmware */
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED = 3,
+ /* Flag attribute to indicate if driver provides additional channel
+ * capability as part of scan operation
+ */
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT = 4,
+ /* Flag attribute to indicate interface status is UP */
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_AP_UP = 5,
+ /* Operating mode (u8) of interface. Takes one of enum nl80211_iftype
+ * values.
+ */
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_SAP_MODE = 6,
+ /* Channel width (u8). It takes one of enum nl80211_chan_width values.
+ * This is the upper bound of channel width. ACS logic should try to get
+ * a channel with the specified width and if not found, look for lower
+ * values.
+ */
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH = 7,
+ /* This (u8) will hold values of one of enum nl80211_bands */
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND = 8,
+ /* PHY/HW mode (u8). Takes one of enum qca_wlan_vendor_acs_hw_mode
+ * values
+ */
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE = 9,
+ /* Array of (u32) supported frequency list among which ACS should choose
+ * best frequency.
+ */
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_FREQ_LIST = 10,
+ /* Preferred channel list by the driver which will have array of nested
+ * values as per enum qca_wlan_vendor_attr_pcl attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL = 11,
+ /* Array of nested attribute for each channel. It takes attr as defined
+ * in enum qca_wlan_vendor_external_acs_event_chan_info_attr.
+ */
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO = 12,
+ /* External ACS policy such as PCL mandatory, PCL preferred, etc.
+ * It uses values defined in enum
+ * qca_wlan_vendor_attr_external_acs_policy.
+ */
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_POLICY = 13,
+ /* Reference RF Operating Parameter (RROP) availability information
+ * (u16). It uses values defined in enum
+ * qca_wlan_vendor_attr_rropavail_info.
+ */
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_RROPAVAIL_INFO = 14,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_LAST,
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_MAX =
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_LAST - 1,
+};
+
+/**
+ * qca_wlan_vendor_attr_external_acs_channels: Attributes to vendor subcmd
+ * QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS. This carries a list of channels
+ * in priority order as decided after ACS operation in userspace.
+ */
+enum qca_wlan_vendor_attr_external_acs_channels {
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_INVALID = 0,
+
+ /* One of reason code (u8) from enum qca_wlan_vendor_acs_select_reason
+ */
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON = 1,
+
+ /* Array of nested values for each channel with following attributes:
+ * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_BAND,
+ * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY,
+ * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY,
+ * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0,
+ * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1,
+ * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
+ */
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST = 2,
+ /* This (u8) will hold values of one of enum nl80211_bands */
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_BAND = 3,
+ /* Primary channel (u8) */
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY = 4,
+ /* Secondary channel (u8) used for HT 40 MHz channels */
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY = 5,
+ /* VHT seg0 channel (u8) */
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0 = 6,
+ /* VHT seg1 channel (u8) */
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1 = 7,
+ /* Channel width (u8). Takes one of enum nl80211_chan_width values. */
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH = 8,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LAST,
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX =
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LAST - 1
+};
+
+enum qca_chip_power_save_failure_reason {
+ /* Indicates if the reason for the failure is due to a protocol
+ * layer/module.
+ */
+ QCA_CHIP_POWER_SAVE_FAILURE_REASON_PROTOCOL = 0,
+ /* Indicates if the reason for the failure is due to a hardware issue.
+ */
+ QCA_CHIP_POWER_SAVE_FAILURE_REASON_HARDWARE = 1,
+};
+
+/**
+ * qca_attr_chip_power_save_failure: Attributes to vendor subcmd
+ * QCA_NL80211_VENDOR_SUBCMD_CHIP_PWRSAVE_FAILURE. This carries the requisite
+ * information leading to the power save failure.
+ */
+enum qca_attr_chip_power_save_failure {
+ QCA_ATTR_CHIP_POWER_SAVE_FAILURE_INVALID = 0,
+ /* Reason to cause the power save failure.
+ * These reasons are represented by
+ * enum qca_chip_power_save_failure_reason.
+ */
+ QCA_ATTR_CHIP_POWER_SAVE_FAILURE_REASON = 1,
+
+ /* keep last */
+ QCA_ATTR_CHIP_POWER_SAVE_FAILURE_LAST,
+ QCA_ATTR_CHIP_POWER_SAVE_FAILURE_MAX =
+ QCA_ATTR_CHIP_POWER_SAVE_FAILURE_LAST - 1,
+};
+
+/**
+ * qca_wlan_vendor_nud_stats_data_pkt_flags: Flag representing the various
+ * data types for which the stats have to get collected.
+ */
+enum qca_wlan_vendor_nud_stats_data_pkt_flags {
+ QCA_WLAN_VENDOR_NUD_STATS_DATA_ARP = 1 << 0,
+ QCA_WLAN_VENDOR_NUD_STATS_DATA_DNS = 1 << 1,
+ QCA_WLAN_VENDOR_NUD_STATS_DATA_TCP_HANDSHAKE = 1 << 2,
+ QCA_WLAN_VENDOR_NUD_STATS_DATA_ICMPV4 = 1 << 3,
+ QCA_WLAN_VENDOR_NUD_STATS_DATA_ICMPV6 = 1 << 4,
+ /* Used by QCA_ATTR_NUD_STATS_PKT_TYPE only in nud stats get
+ * to represent the stats of respective data type.
+ */
+ QCA_WLAN_VENDOR_NUD_STATS_DATA_TCP_SYN = 1 << 5,
+ QCA_WLAN_VENDOR_NUD_STATS_DATA_TCP_SYN_ACK = 1 << 6,
+ QCA_WLAN_VENDOR_NUD_STATS_DATA_TCP_ACK = 1 << 7,
+};
+
+enum qca_wlan_vendor_nud_stats_set_data_pkt_info {
+ QCA_ATTR_NUD_STATS_DATA_PKT_INFO_INVALID = 0,
+ /* Represents the data packet type to be monitored (u32).
+ * Host driver tracks the stats corresponding to each data frame
+ * represented by these flags.
+ * These data packets are represented by
+ * enum qca_wlan_vendor_nud_stats_data_pkt_flags
+ */
+ QCA_ATTR_NUD_STATS_DATA_PKT_INFO_TYPE = 1,
+ /* Name corresponding to the DNS frame for which the respective DNS
+ * stats have to get monitored (string). Max string length 255.
+ */
+ QCA_ATTR_NUD_STATS_DATA_PKT_INFO_DNS_DOMAIN_NAME = 2,
+ /* source port on which the respective proto stats have to get
+ * collected (u32).
+ */
+ QCA_ATTR_NUD_STATS_DATA_PKT_INFO_SRC_PORT = 3,
+ /* destination port on which the respective proto stats have to get
+ * collected (u32).
+ */
+ QCA_ATTR_NUD_STATS_DATA_PKT_INFO_DEST_PORT = 4,
+ /* IPv4 address for which the destined data packets have to be
+ * monitored. (in network byte order), u32.
+ */
+ QCA_ATTR_NUD_STATS_DATA_PKT_INFO_DEST_IPV4 = 5,
+ /* IPv6 address for which the destined data packets have to be
+ * monitored. (in network byte order), 16 bytes array.
+ */
+ QCA_ATTR_NUD_STATS_DATA_PKT_INFO_DEST_IPV6 = 6,
+
+ QCA_ATTR_NUD_STATS_DATA_PKT_INFO_LAST,
+ QCA_ATTR_NUD_STATS_DATA_PKT_INFO_MAX =
+ QCA_ATTR_NUD_STATS_DATA_PKT_INFO_LAST - 1,
+};
+
+/**
+ * qca_wlan_vendor_attr_nud_stats_set: Attributes to vendor subcmd
+ * QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET. This carries the requisite
+ * information to start/stop the NUD statistics collection.
+ */
+enum qca_attr_nud_stats_set {
+ QCA_ATTR_NUD_STATS_SET_INVALID = 0,
+
+ /* Flag to start/stop the NUD statistics collection.
+ * Start - If included, Stop - If not included
+ */
+ QCA_ATTR_NUD_STATS_SET_START = 1,
+ /* IPv4 address of the default gateway (in network byte order), u32 */
+ QCA_ATTR_NUD_STATS_GW_IPV4 = 2,
+ /* Represents the list of data packet types to be monitored.
+ * Host driver tracks the stats corresponding to each data frame
+ * represented by these flags.
+ * These data packets are represented by
+ * enum qca_wlan_vendor_nud_stats_set_data_pkt_info
+ */
+ QCA_ATTR_NUD_STATS_SET_DATA_PKT_INFO = 3,
+
+ /* keep last */
+ QCA_ATTR_NUD_STATS_SET_LAST,
+ QCA_ATTR_NUD_STATS_SET_MAX =
+ QCA_ATTR_NUD_STATS_SET_LAST - 1,
+};
+
+enum qca_attr_nud_data_stats {
+ QCA_ATTR_NUD_DATA_STATS_INVALID = 0,
+ /* Data packet type for which the stats are collected (u32).
+ * Represented by enum qca_wlan_vendor_nud_stats_data_pkt_flags
+ */
+ QCA_ATTR_NUD_STATS_PKT_TYPE = 1,
+ /* Name corresponding to the DNS frame for which the respective DNS
+ * stats are monitored (string). Max string length 255.
+ */
+ QCA_ATTR_NUD_STATS_PKT_DNS_DOMAIN_NAME = 2,
+ /* source port on which the respective proto stats are collected (u32).
+ */
+ QCA_ATTR_NUD_STATS_PKT_SRC_PORT = 3,
+ /* destination port on which the respective proto stats are collected
+ * (u32).
+ */
+ QCA_ATTR_NUD_STATS_PKT_DEST_PORT = 4,
+ /* IPv4 address for which the destined data packets have to be
+ * monitored. (in network byte order), u32.
+ */
+ QCA_ATTR_NUD_STATS_PKT_DEST_IPV4 = 5,
+ /* IPv6 address for which the destined data packets have to be
+ * monitored. (in network byte order), 16 bytes array.
+ */
+ QCA_ATTR_NUD_STATS_PKT_DEST_IPV6 = 6,
+ /* Data packet Request count received from netdev (u32). */
+ QCA_ATTR_NUD_STATS_PKT_REQ_COUNT_FROM_NETDEV = 7,
+ /* Data packet Request count sent to lower MAC from upper MAC (u32). */
+ QCA_ATTR_NUD_STATS_PKT_REQ_COUNT_TO_LOWER_MAC = 8,
+ /* Data packet Request count received by lower MAC from upper MAC
+ * (u32)
+ */
+ QCA_ATTR_NUD_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC = 9,
+ /* Data packet Request count successfully transmitted by the device
+ * (u32)
+ */
+ QCA_ATTR_NUD_STATS_PKT_REQ_COUNT_TX_SUCCESS = 10,
+ /* Data packet Response count received by lower MAC (u32) */
+ QCA_ATTR_NUD_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC = 11,
+ /* Data packet Response count received by upper MAC (u32) */
+ QCA_ATTR_NUD_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC = 12,
+ /* Data packet Response count delivered to netdev (u32) */
+ QCA_ATTR_NUD_STATS_PKT_RSP_COUNT_TO_NETDEV = 13,
+ /* Data Packet Response count that are dropped out of order (u32) */
+ QCA_ATTR_NUD_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP = 14,
+
+ /* keep last */
+ QCA_ATTR_NUD_DATA_STATS_LAST,
+ QCA_ATTR_NUD_DATA_STATS_MAX =
+ QCA_ATTR_NUD_DATA_STATS_LAST - 1,
+};
+
+/**
+ * qca_attr_nud_stats_get: Attributes to vendor subcmd
+ * QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET. This carries the requisite
+ * NUD statistics collected when queried.
+ */
+enum qca_attr_nud_stats_get {
+ QCA_ATTR_NUD_STATS_GET_INVALID = 0,
+ /* ARP Request count from netdev (u32) */
+ QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV = 1,
+ /* ARP Request count sent to lower MAC from upper MAC (u32) */
+ QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC = 2,
+ /* ARP Request count received by lower MAC from upper MAC (u32) */
+ QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC = 3,
+ /* ARP Request count successfully transmitted by the device (u32) */
+ QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS = 4,
+ /* ARP Response count received by lower MAC (u32) */
+ QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC = 5,
+ /* ARP Response count received by upper MAC (u32) */
+ QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC = 6,
+ /* ARP Response count delivered to netdev (u32) */
+ QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV = 7,
+ /* ARP Response count dropped due to out of order reception (u32) */
+ QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP = 8,
+ /* Flag indicating if the station's link to the AP is active.
+ * Active Link - If included, Inactive link - If not included
+ */
+ QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE = 9,
+ /* Flag indicating if there is any duplicate address detected (DAD).
+ * Yes - If detected, No - If not detected.
+ */
+ QCA_ATTR_NUD_STATS_IS_DAD = 10,
+ /* List of Data packet types for which the stats are requested.
+ * This list does not carry ARP stats as they are done by the
+ * above attributes. Represented by enum qca_attr_nud_data_stats.
+ */
+ QCA_ATTR_NUD_STATS_DATA_PKT_STATS = 11,
+
+ /* keep last */
+ QCA_ATTR_NUD_STATS_GET_LAST,
+ QCA_ATTR_NUD_STATS_GET_MAX =
+ QCA_ATTR_NUD_STATS_GET_LAST - 1,
+};
+
+enum qca_wlan_btm_candidate_status {
+ QCA_STATUS_ACCEPT = 0,
+ QCA_STATUS_REJECT_EXCESSIVE_FRAME_LOSS_EXPECTED = 1,
+ QCA_STATUS_REJECT_EXCESSIVE_DELAY_EXPECTED = 2,
+ QCA_STATUS_REJECT_INSUFFICIENT_QOS_CAPACITY = 3,
+ QCA_STATUS_REJECT_LOW_RSSI = 4,
+ QCA_STATUS_REJECT_HIGH_INTERFERENCE = 5,
+ QCA_STATUS_REJECT_UNKNOWN = 6,
+};
+
+enum qca_wlan_vendor_attr_btm_candidate_info {
+ QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_INVALID = 0,
+
+ /* 6-byte MAC address representing the BSSID of transition candidate */
+ QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_BSSID = 1,
+ /* Unsigned 32-bit value from enum qca_wlan_btm_candidate_status
+ * returned by the driver. It says whether the BSSID provided in
+ * QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_BSSID is acceptable by
+ * the driver, if not it specifies the reason for rejection.
+ * Note that the user-space can overwrite the transition reject reason
+ * codes provided by driver based on more information.
+ */
+ QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_STATUS = 2,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_MAX =
+ QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_AFTER_LAST - 1,
+};
+
+enum qca_attr_trace_level {
+ QCA_ATTR_TRACE_LEVEL_INVALID = 0,
+ /*
+ * Nested array of the following attributes:
+ * QCA_ATTR_TRACE_LEVEL_MODULE,
+ * QCA_ATTR_TRACE_LEVEL_MASK.
+ */
+ QCA_ATTR_TRACE_LEVEL_PARAM = 1,
+ /*
+ * Specific QCA host driver module. Please refer to the QCA host
+ * driver implementation to get the specific module ID.
+ */
+ QCA_ATTR_TRACE_LEVEL_MODULE = 2,
+ /* Different trace level masks represented in the QCA host driver. */
+ QCA_ATTR_TRACE_LEVEL_MASK = 3,
+
+ /* keep last */
+ QCA_ATTR_TRACE_LEVEL_AFTER_LAST,
+ QCA_ATTR_TRACE_LEVEL_MAX =
+ QCA_ATTR_TRACE_LEVEL_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_get_he_capabilities - IEEE 802.11ax HE capabilities
+ */
+enum qca_wlan_vendor_attr_get_he_capabilities {
+ QCA_WLAN_VENDOR_ATTR_HE_CAPABILITIES_INVALID = 0,
+ /* Whether HE capabilities is supported
+ * (u8 attribute: 0 = not supported, 1 = supported)
+ */
+ QCA_WLAN_VENDOR_ATTR_HE_SUPPORTED = 1,
+ /* HE PHY capabilities, array of 3 u32 values */
+ QCA_WLAN_VENDOR_ATTR_PHY_CAPAB = 2,
+ /* HE MAC capabilities (u32 attribute) */
+ QCA_WLAN_VENDOR_ATTR_MAC_CAPAB = 3,
+ /* HE MCS map (u32 attribute) */
+ QCA_WLAN_VENDOR_ATTR_HE_MCS = 4,
+ /* Number of SS (u32 attribute) */
+ QCA_WLAN_VENDOR_ATTR_NUM_SS = 5,
+ /* RU count (u32 attribute) */
+ QCA_WLAN_VENDOR_ATTR_RU_IDX_MASK = 6,
+ /* PPE threshold data, array of 8 u32 values */
+ QCA_WLAN_VENDOR_ATTR_PPE_THRESHOLD = 7,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_HE_CAPABILITIES_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_HE_CAPABILITIES_MAX =
+ QCA_WLAN_VENDOR_ATTR_HE_CAPABILITIES_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_spectral_scan - Spectral scan config parameters
+ */
+enum qca_wlan_vendor_attr_spectral_scan {
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INVALID = 0,
+ /* Number of times the chip enters spectral scan mode before
+ * deactivating spectral scans. When set to 0, chip will enter spectral
+ * scan mode continuously. u32 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_COUNT = 1,
+ /* Spectral scan period. Period increment resolution is 256*Tclk,
+ * where Tclk = 1/44 MHz (Gmode), 1/40 MHz (Amode). u32 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_PERIOD = 2,
+ /* Spectral scan priority. u32 attribute. */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PRIORITY = 3,
+ /* Number of FFT data points to compute. u32 attribute. */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_SIZE = 4,
+ /* Enable targeted gain change before starting the spectral scan FFT.
+ * u32 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_GC_ENA = 5,
+ /* Restart a queued spectral scan. u32 attribute. */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RESTART_ENA = 6,
+ /* Noise floor reference number for the calculation of bin power.
+ * u32 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NOISE_FLOOR_REF = 7,
+ /* Disallow spectral scan triggers after TX/RX packets by setting
+ * this delay value to roughly SIFS time period or greater.
+ * u32 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INIT_DELAY = 8,
+ /* Number of strong bins (inclusive) per sub-channel, below
+ * which a signal is declared a narrow band tone. u32 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NB_TONE_THR = 9,
+ /* Specify the threshold over which a bin is declared strong (for
+ * scan bandwidth analysis). u32 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_STR_BIN_THR = 10,
+ /* Spectral scan report mode. u32 attribute. */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_WB_RPT_MODE = 11,
+ /* RSSI report mode, if the ADC RSSI is below
+ * QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR,
+ * then FFTs will not trigger, but timestamps and summaries get
+ * reported. u32 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_RPT_MODE = 12,
+ /* ADC RSSI must be greater than or equal to this threshold (signed dB)
+ * to ensure spectral scan reporting with normal error code.
+ * u32 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR = 13,
+ /* Format of frequency bin magnitude for spectral scan triggered FFTs:
+ * 0: linear magnitude, 1: log magnitude (20*log10(lin_mag)).
+ * u32 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PWR_FORMAT = 14,
+ /* Format of FFT report to software for spectral scan triggered FFTs.
+ * 0: No FFT report (only spectral scan summary report)
+ * 1: 2-dword summary of metrics for each completed FFT + spectral scan
+ * report
+ * 2: 2-dword summary of metrics for each completed FFT + 1x-oversampled
+ * bins (in-band) per FFT + spectral scan summary report
+ * 3: 2-dword summary of metrics for each completed FFT + 2x-oversampled
+ * bins (all) per FFT + spectral scan summary report
+ * u32 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RPT_MODE = 15,
+ /* Number of LSBs to shift out in order to scale the FFT bins.
+ * u32 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BIN_SCALE = 16,
+ /* Set to 1 (with spectral_scan_pwr_format=1), to report bin magnitudes
+ * in dBm power. u32 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DBM_ADJ = 17,
+ /* Per chain enable mask to select input ADC for search FFT.
+ * u32 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_CHN_MASK = 18,
+ /* An unsigned 64-bit integer provided by host driver to identify the
+ * spectral scan request. This attribute is included in the scan
+ * response message for @QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_START
+ * and used as an attribute in
+ * @QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_STOP to identify the
+ * specific scan to be stopped.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COOKIE = 19,
+ /* Skip interval for FFT reports. u32 attribute */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_PERIOD = 20,
+ /* Set to report only one set of FFT results.
+ * u32 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SHORT_REPORT = 21,
+ /* Debug level for spectral module in driver.
+ * 0 : Verbosity level 0
+ * 1 : Verbosity level 1
+ * 2 : Verbosity level 2
+ * 3 : Matched filterID display
+ * 4 : One time dump of FFT report
+ * u32 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL = 22,
+ /* Type of spectral scan request. u32 attribute.
+ * It uses values defined in enum
+ * qca_wlan_vendor_attr_spectral_scan_request_type.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE = 23,
+
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX =
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_spectral_diag_stats - Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_DIAG_STATS.
+ */
+enum qca_wlan_vendor_attr_spectral_diag_stats {
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_INVALID = 0,
+ /* Number of spectral TLV signature mismatches.
+ * u64 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_SIG_MISMATCH = 1,
+ /* Number of spectral phyerror events with insufficient length when
+ * parsing for secondary 80 search FFT report. u64 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_SEC80_SFFT_INSUFFLEN = 2,
+ /* Number of spectral phyerror events without secondary 80
+ * search FFT report. u64 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_NOSEC80_SFFT = 3,
+ /* Number of spectral phyerror events with vht operation segment 1 id
+ * mismatches in search fft report. u64 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_VHTSEG1ID_MISMATCH = 4,
+ /* Number of spectral phyerror events with vht operation segment 2 id
+ * mismatches in search fft report. u64 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_VHTSEG2ID_MISMATCH = 5,
+
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_MAX =
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_spectral_cap - Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_CAP_INFO.
+ */
+enum qca_wlan_vendor_attr_spectral_cap {
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_INVALID = 0,
+ /* Flag attribute to indicate phydiag capability */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_PHYDIAG = 1,
+ /* Flag attribute to indicate radar detection capability */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_RADAR = 2,
+ /* Flag attribute to indicate spectral capability */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_SPECTRAL = 3,
+ /* Flag attribute to indicate advanced spectral capability */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_ADVANCED_SPECTRAL = 4,
+ /* Spectral hardware generation. u32 attribute.
+ * It uses values defined in enum
+ * qca_wlan_vendor_spectral_scan_cap_hw_gen.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_HW_GEN = 5,
+ /* Spectral bin scaling formula ID. u16 attribute.
+ * It uses values defined in enum
+ * qca_wlan_vendor_spectral_scan_cap_formula_id.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_FORMULA_ID = 6,
+ /* Spectral bin scaling param - low level offset.
+ * s16 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_LOW_LEVEL_OFFSET = 7,
+ /* Spectral bin scaling param - high level offset.
+ * s16 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_HIGH_LEVEL_OFFSET = 8,
+ /* Spectral bin scaling param - RSSI threshold.
+ * s16 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_RSSI_THR = 9,
+ /* Spectral bin scaling param - default AGC max gain.
+ * u8 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_DEFAULT_AGC_MAX_GAIN = 10,
+
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_MAX =
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_spectral_scan_status - used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_STATUS.
+ */
+enum qca_wlan_vendor_attr_spectral_scan_status {
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_INVALID = 0,
+ /* Flag attribute to indicate whether spectral scan is enabled */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_IS_ENABLED = 1,
+ /* Flag attribute to indicate whether spectral scan is in progress*/
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_IS_ACTIVE = 2,
+
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_MAX =
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_AFTER_LAST - 1,
+};
+
+/**
+ * qca_wlan_vendor_attr_spectral_scan_request_type: Attribute values for
+ * QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE to the vendor subcmd
+ * QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_START. This represents the
+ * spectral scan request types.
+ * @QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE_SCAN_AND_CONFIG: Request to
+ * set the spectral parameters and start scan.
+ * @QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE_SCAN: Request to
+ * only set the spectral parameters.
+ * @QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE_CONFIG: Request to
+ * only start the spectral scan.
+ */
+enum qca_wlan_vendor_attr_spectral_scan_request_type {
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE_SCAN_AND_CONFIG,
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE_SCAN,
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE_CONFIG,
+};
+
+/**
+ * qca_wlan_vendor_spectral_scan_cap_hw_gen: Attribute values for
+ * QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_HW_GEN to the vendor subcmd
+ * QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_CAP_INFO. This represents the
+ * spectral hardware generation.
+ * @QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_HW_GEN_1: generation 1
+ * @QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_HW_GEN_2: generation 2
+ * @QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_HW_GEN_3: generation 3
+ */
+enum qca_wlan_vendor_spectral_scan_cap_hw_gen {
+ QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_HW_GEN_1 = 0,
+ QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_HW_GEN_2 = 1,
+ QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_HW_GEN_3 = 2,
+};
+
+enum qca_wlan_vendor_tos {
+ QCA_WLAN_VENDOR_TOS_BK = 0,
+ QCA_WLAN_VENDOR_TOS_BE = 1,
+ QCA_WLAN_VENDOR_TOS_VI = 2,
+ QCA_WLAN_VENDOR_TOS_VO = 3,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_active_tos - Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_ACTIVE_TOS.
+ */
+enum qca_wlan_vendor_attr_active_tos {
+ QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS_INVALID = 0,
+ /* Type Of Service - Represented by qca_wlan_vendor_tos */
+ QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS = 1,
+ /* Flag attribute representing the start (attribute included) or stop
+ * (attribute not included) of the respective TOS.
+ */
+ QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS_START = 2,
+};
+
+enum qca_wlan_vendor_hang_reason {
+ /* Unspecified reason */
+ QCA_WLAN_HANG_REASON_UNSPECIFIED = 0,
+ /* No Map for the MAC entry for the received frame */
+ QCA_WLAN_HANG_RX_HASH_NO_ENTRY_FOUND = 1,
+ /* Peer deletion timeout happened */
+ QCA_WLAN_HANG_PEER_DELETION_TIMEDOUT = 2,
+ /* Peer unmap timeout */
+ QCA_WLAN_HANG_PEER_UNMAP_TIMEDOUT = 3,
+ /* Scan request timed out */
+ QCA_WLAN_HANG_SCAN_REQ_EXPIRED = 4,
+ /* Consecutive Scan attempt failures */
+ QCA_WLAN_HANG_SCAN_ATTEMPT_FAILURES = 5,
+ /* Unable to get the message buffer */
+ QCA_WLAN_HANG_GET_MSG_BUFF_FAILURE = 6,
+ /* Current command processing is timedout */
+ QCA_WLAN_HANG_ACTIVE_LIST_TIMEOUT = 7,
+ /* Timeout for an ACK from FW for suspend request */
+ QCA_WLAN_HANG_SUSPEND_TIMEOUT = 8,
+ /* Timeout for an ACK from FW for resume request */
+ QCA_WLAN_HANG_RESUME_TIMEOUT = 9,
+ /* Transmission timeout for consecutive data frames */
+ QCA_WLAN_HANG_TRANSMISSIONS_TIMEOUT = 10,
+ /* Timeout for the TX completion status of data frame */
+ QCA_WLAN_HANG_TX_COMPLETE_TIMEOUT = 11,
+ /* DXE failure for TX/RX, DXE resource unavailability */
+ QCA_WLAN_HANG_DXE_FAILURE = 12,
+ /* WMI pending commands exceed the maximum count */
+ QCA_WLAN_HANG_WMI_EXCEED_MAX_PENDING_CMDS = 13,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_hang - Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_HANG.
+ */
+enum qca_wlan_vendor_attr_hang {
+ QCA_WLAN_VENDOR_ATTR_HANG_INVALID = 0,
+ /* Reason for the hang - u32 attribute with a value from enum
+ * qca_wlan_vendor_hang_reason.
+ */
+ QCA_WLAN_VENDOR_ATTR_HANG_REASON = 1,
+
+ QCA_WLAN_VENDOR_ATTR_HANG_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_HANG_MAX =
+ QCA_WLAN_VENDOR_ATTR_HANG_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_flush_pending - Attributes for
+ * flushing pending traffic in firmware.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_PEER_ADDR: Configure peer MAC address.
+ * @QCA_WLAN_VENDOR_ATTR_AC: Configure access category of the pending
+ * packets. It is u8 value with bit 0~3 represent AC_BE, AC_BK,
+ * AC_VI, AC_VO respectively. Set the corresponding bit to 1 to
+ * flush packets with access category.
+ */
+enum qca_wlan_vendor_attr_flush_pending {
+ QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_PEER_ADDR = 1,
+ QCA_WLAN_VENDOR_ATTR_AC = 2,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_MAX =
+ QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_AFTER_LAST - 1,
+};
+
+/**
+ * qca_wlan_vendor_spectral_scan_cap_formula_id: Attribute values for
+ * QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_FORMULA_ID in the vendor subcmd
+ * QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_CAP_INFO. This represents the
+ * Spectral bin scaling formula ID.
+ * @QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_NO_SCALING: No scaling
+ * @QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_AGC_GAIN_RSSI_CORR_BASED: AGC gain
+ * and RSSI threshold based formula.
+ */
+enum qca_wlan_vendor_spectral_scan_cap_formula_id {
+ QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_NO_SCALING = 0,
+ QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_AGC_GAIN_RSSI_CORR_BASED = 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_rropavail_info - Specifies whether Representative
+ * RF Operating Parameter (RROP) information is available, and if so, at which
+ * point in the application-driver interaction sequence it can be retrieved by
+ * the application from the driver. This point may vary by architecture and
+ * other factors. This is a u16 value.
+ */
+enum qca_wlan_vendor_attr_rropavail_info {
+ /* RROP information is unavailable. */
+ QCA_WLAN_VENDOR_ATTR_RROPAVAIL_INFO_UNAVAILABLE,
+ /* RROP information is available and the application can retrieve the
+ * information after receiving an QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
+ * event from the driver.
+ */
+ QCA_WLAN_VENDOR_ATTR_RROPAVAIL_INFO_EXTERNAL_ACS_START,
+ /* RROP information is available only after a vendor specific scan
+ * (requested using QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN) has
+ * successfully completed. The application can retrieve the information
+ * after receiving the QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE event from
+ * the driver.
+ */
+ QCA_WLAN_VENDOR_ATTR_RROPAVAIL_INFO_VSCAN_END,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_rrop_info - Specifies vendor specific
+ * Representative RF Operating Parameter (RROP) information. It is sent for the
+ * vendor command QCA_NL80211_VENDOR_SUBCMD_GET_RROP_INFO. This information is
+ * intended for use by external Auto Channel Selection applications. It provides
+ * guidance values for some RF parameters that are used by the system during
+ * operation. These values could vary by channel, band, radio, and so on.
+ */
+enum qca_wlan_vendor_attr_rrop_info {
+ QCA_WLAN_VENDOR_ATTR_RROP_INFO_INVALID = 0,
+
+ /* Representative Tx Power List (RTPL) which has an array of nested
+ * values as per attributes in enum qca_wlan_vendor_attr_rtplinst.
+ */
+ QCA_WLAN_VENDOR_ATTR_RROP_INFO_RTPL = 1,
+
+ QCA_WLAN_VENDOR_ATTR_RROP_INFO_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_RROP_INFO_MAX =
+ QCA_WLAN_VENDOR_ATTR_RROP_INFO_AFTER_LAST - 1
+};
+
+/**
+ * enum qca_wlan_vendor_attr_rtplinst - Specifies attributes for individual list
+ * entry instances in the Representative Tx Power List (RTPL). It provides
+ * simplified power values intended for helping external Auto channel Selection
+ * applications compare potential Tx power performance between channels, other
+ * operating conditions remaining identical. These values are not necessarily
+ * the actual Tx power values that will be used by the system. They are also not
+ * necessarily the max or average values that will be used. Instead, they are
+ * relative, summarized keys for algorithmic use computed by the driver or
+ * underlying firmware considering a number of vendor specific factors.
+ */
+enum qca_wlan_vendor_attr_rtplinst {
+ QCA_WLAN_VENDOR_ATTR_RTPLINST_INVALID = 0,
+
+ /* Primary channel number (u8) */
+ QCA_WLAN_VENDOR_ATTR_RTPLINST_PRIMARY = 1,
+ /* Representative Tx power in dBm (s32) with emphasis on throughput. */
+ QCA_WLAN_VENDOR_ATTR_RTPLINST_TXPOWER_THROUGHPUT = 2,
+ /* Representative Tx power in dBm (s32) with emphasis on range. */
+ QCA_WLAN_VENDOR_ATTR_RTPLINST_TXPOWER_RANGE = 3,
+
+ QCA_WLAN_VENDOR_ATTR_RTPLINST_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_RTPLINST_MAX =
+ QCA_WLAN_VENDOR_ATTR_RTPLINST_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_config_latency_level - Level for
+ * wlan latency module.
+ *
+ * There will be various of Wi-Fi functionality like scan/roaming/adaptive
+ * power saving which would causing data exchange out of service, this
+ * would be a big impact on latency. For latency sensitive applications over
+ * Wi-Fi are intolerant to such operations and thus would configure them
+ * to meet their respective needs. It is well understood by such applications
+ * that altering the default behavior would degrade the Wi-Fi functionality
+ * w.r.t the above pointed WLAN operations.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_NORMAL:
+ * Default WLAN operation level which throughput orientated.
+ * @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_MODERATE:
+ * Use moderate level to improve latency by limit scan duration.
+ * @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_LOW:
+ * Use low latency level to benifit application like concurrent
+ * downloading or video streaming via constraint scan/adaptive PS.
+ * @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_ULTRALOW:
+ * Use ultra low latency level to benefit for gaming/voice
+ * application via constraint scan/roaming/adaptive PS.
+ */
+enum qca_wlan_vendor_attr_config_latency_level {
+ QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_NORMAL = 1,
+ QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_MODERATE = 2,
+ QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_LOW = 3,
+ QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_ULTRALOW = 4,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_MAX =
+ QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_wlan_mac - Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO.
+ */
+enum qca_wlan_vendor_attr_mac {
+ QCA_WLAN_VENDOR_ATTR_MAC_INVALID = 0,
+
+ /* MAC mode info list which has an array of nested values as
+ * per attributes in enum qca_wlan_vendor_attr_mac_mode_info.
+ */
+ QCA_WLAN_VENDOR_ATTR_MAC_INFO = 1,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_MAC_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_MAC_MAX =
+ QCA_WLAN_VENDOR_ATTR_MAC_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_mac_iface_info - Information of the connected
+ * Wi-Fi netdev interface on a respective MAC.
+ * Used by the attribute QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO.
+ */
+enum qca_wlan_vendor_attr_mac_iface_info {
+ QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_INVALID = 0,
+ /* Wi-Fi netdev's interface index (u32) */
+ QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_IFINDEX = 1,
+ /* Associated frequency in MHz of the connected Wi-Fi interface (u32) */
+ QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_FREQ = 2,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_MAX =
+ QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_mac_info - Points to MAC the information.
+ * Used by the attribute QCA_WLAN_VENDOR_ATTR_MAC_INFO of the
+ * vendor command QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO.
+ */
+enum qca_wlan_vendor_attr_mac_info {
+ QCA_WLAN_VENDOR_ATTR_MAC_INFO_INVALID = 0,
+ /* Hardware MAC ID associated for the MAC (u32) */
+ QCA_WLAN_VENDOR_ATTR_MAC_INFO_MAC_ID = 1,
+ /* Band supported by the MAC at a given point.
+ * This is a u32 bitmask of BIT(NL80211_BAND_*) as described in %enum
+ * nl80211_band.
+ */
+ QCA_WLAN_VENDOR_ATTR_MAC_INFO_BAND = 2,
+ /* Refers to list of WLAN netdev interfaces associated with this MAC.
+ * Represented by enum qca_wlan_vendor_attr_mac_iface_info.
+ */
+ QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO = 3,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_MAC_INFO_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_MAC_INFO_MAX =
+ QCA_WLAN_VENDOR_ATTR_MAC_INFO_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_get_logger_features - Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET.
+ */
+enum qca_wlan_vendor_attr_get_logger_features {
+ QCA_WLAN_VENDOR_ATTR_LOGGER_INVALID = 0,
+ /* Unsigned 32-bit enum value of wifi_logger_supported_features */
+ QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED = 1,
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_LOGGER_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_LOGGER_MAX =
+ QCA_WLAN_VENDOR_ATTR_LOGGER_AFTER_LAST - 1,
+};
+
+/**
+ * enum wifi_logger_supported_features - Values for supported logger features
+ */
+enum wifi_logger_supported_features {
+ WIFI_LOGGER_MEMORY_DUMP_FEATURE = (1 << (0)),
+ WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_FEATURE = (1 << (1)),
+ WIFI_LOGGER_CONNECT_EVENT_FEATURE = (1 << (2)),
+ WIFI_LOGGER_POWER_EVENT_FEATURE = (1 << (3)),
+ WIFI_LOGGER_WAKE_LOCK_FEATURE = (1 << (4)),
+ WIFI_LOGGER_VERBOSE_FEATURE = (1 << (5)),
+ WIFI_LOGGER_WATCHDOG_TIMER_FEATURE = (1 << (6)),
+ WIFI_LOGGER_DRIVER_DUMP_FEATURE = (1 << (7)),
+ WIFI_LOGGER_PACKET_FATE_FEATURE = (1 << (8)),
+};
+
+/**
+ * enum qca_wlan_tdls_caps_features_supported - Values for TDLS get
+ * capabilities features
+ */
+enum qca_wlan_tdls_caps_features_supported {
+ WIFI_TDLS_SUPPORT = (1 << (0)),
+ WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT = (1 << (1)),
+ WIFI_TDLS_OFFCHANNEL_SUPPORT = (1 << (2))
+};
+
+/**
+ * enum qca_wlan_vendor_attr_tdls_get_capabilities - Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES.
+ */
+enum qca_wlan_vendor_attr_tdls_get_capabilities {
+ QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_INVALID = 0,
+ /* Indicates the max concurrent sessions */
+ /* Unsigned 32-bit value */
+ QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS,
+ /* Indicates the support for features */
+ /* Unsigned 32-bit bitmap qca_wlan_tdls_caps_features_supported
+ */
+ QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX =
+ QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_offloaded_packets_sending_control - Offload packets control
+ * command used as value for the attribute
+ * QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL.
+ */
+enum qca_wlan_offloaded_packets_sending_control {
+ QCA_WLAN_OFFLOADED_PACKETS_SENDING_CONTROL_INVALID = 0,
+ QCA_WLAN_OFFLOADED_PACKETS_SENDING_START,
+ QCA_WLAN_OFFLOADED_PACKETS_SENDING_STOP
+};
+
+/**
+ * enum qca_wlan_vendor_attr_offloaded_packets - Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS.
+ */
+enum qca_wlan_vendor_attr_offloaded_packets {
+ QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_INVALID = 0,
+ /* Takes valid value from the enum
+ * qca_wlan_offloaded_packets_sending_control
+ * Unsigned 32-bit value
+ */
+ QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL,
+ /* Unsigned 32-bit value */
+ QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID,
+ /* array of u8 len: Max packet size */
+ QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA,
+ /* 6-byte MAC address used to represent source MAC address */
+ QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR,
+ /* 6-byte MAC address used to represent destination MAC address */
+ QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR,
+ /* Unsigned 32-bit value, in milli seconds */
+ QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD,
+ /* This optional unsigned 16-bit attribute is used for specifying
+ * ethernet protocol type. If not specified ethertype defaults to IPv4.
+ */
+ QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_ETHER_PROTO_TYPE,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX =
+ QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_rssi_monitoring_control - RSSI control commands used as values
+ * by the attribute QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL.
+ */
+enum qca_wlan_rssi_monitoring_control {
+ QCA_WLAN_RSSI_MONITORING_CONTROL_INVALID = 0,
+ QCA_WLAN_RSSI_MONITORING_START,
+ QCA_WLAN_RSSI_MONITORING_STOP,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_rssi_monitoring - Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI.
+ */
+enum qca_wlan_vendor_attr_rssi_monitoring {
+ QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_INVALID = 0,
+ /* Takes valid value from the enum
+ * qca_wlan_rssi_monitoring_control
+ * Unsigned 32-bit value enum qca_wlan_rssi_monitoring_control
+ */
+ QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL,
+ /* Unsigned 32-bit value */
+ QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
+ /* Signed 8-bit value in dBm */
+ QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI,
+ /* Signed 8-bit value in dBm */
+ QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI,
+ /* attributes to be used/received in callback */
+ /* 6-byte MAC address used to represent current BSSID MAC address */
+ QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
+ /* Signed 8-bit value indicating the current RSSI */
+ QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX =
+ QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_ndp_params - Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_NDP.
+ */
+enum qca_wlan_vendor_attr_ndp_params {
+ QCA_WLAN_VENDOR_ATTR_NDP_PARAM_INVALID = 0,
+ /* Unsigned 32-bit value
+ * enum of sub commands values in qca_wlan_ndp_sub_cmd
+ */
+ QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD,
+ /* Unsigned 16-bit value */
+ QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID,
+ /* NL attributes for data used NDP SUB cmds */
+ /* Unsigned 32-bit value indicating a service info */
+ QCA_WLAN_VENDOR_ATTR_NDP_SERVICE_INSTANCE_ID,
+ /* Unsigned 32-bit value; channel frequency in MHz */
+ QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL,
+ /* Interface Discovery MAC address. An array of 6 Unsigned int8 */
+ QCA_WLAN_VENDOR_ATTR_NDP_PEER_DISCOVERY_MAC_ADDR,
+ /* Interface name on which NDP is being created */
+ QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR,
+ /* Unsigned 32-bit value for security */
+ /* CONFIG_SECURITY is deprecated, use NCS_SK_TYPE/PMK/SCID instead */
+ QCA_WLAN_VENDOR_ATTR_NDP_CONFIG_SECURITY,
+ /* Unsigned 32-bit value for QoS */
+ QCA_WLAN_VENDOR_ATTR_NDP_CONFIG_QOS,
+ /* Array of u8: len = QCA_WLAN_VENDOR_ATTR_NAN_DP_APP_INFO_LEN */
+ QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO,
+ /* Unsigned 32-bit value for NDP instance Id */
+ QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID,
+ /* Array of instance Ids */
+ QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID_ARRAY,
+ /* Unsigned 32-bit value for initiator/responder NDP response code
+ * accept/reject
+ */
+ QCA_WLAN_VENDOR_ATTR_NDP_RESPONSE_CODE,
+ /* NDI MAC address. An array of 6 Unsigned int8 */
+ QCA_WLAN_VENDOR_ATTR_NDP_NDI_MAC_ADDR,
+ /* Unsigned 32-bit value errors types returned by driver
+ * The wifi_nan.h in AOSP project platform/hardware/libhardware_legacy
+ * NanStatusType includes these values.
+ */
+ QCA_WLAN_VENDOR_ATTR_NDP_DRV_RESPONSE_STATUS_TYPE,
+ /* Unsigned 32-bit value error values returned by driver
+ * The nan_i.h in AOSP project platform/hardware/qcom/wlan
+ * NanInternalStatusType includes these values.
+ */
+ QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE,
+ /* Unsigned 32-bit value for Channel setup configuration
+ * The wifi_nan.h in AOSP project platform/hardware/libhardware_legacy
+ * NanDataPathChannelCfg includes these values.
+ */
+ QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_CONFIG,
+ /* Unsigned 32-bit value for Cipher Suite Shared Key Type */
+ QCA_WLAN_VENDOR_ATTR_NDP_CSID,
+ /* Array of u8: len = NAN_PMK_INFO_LEN 32 bytes */
+ QCA_WLAN_VENDOR_ATTR_NDP_PMK,
+ /* Security Context Identifier that contains the PMKID
+ * Array of u8: len = NAN_SCID_BUF_LEN 1024 bytes
+ */
+ QCA_WLAN_VENDOR_ATTR_NDP_SCID,
+ /* Array of u8: len = NAN_SECURITY_MAX_PASSPHRASE_LEN 63 bytes */
+ QCA_WLAN_VENDOR_ATTR_NDP_PASSPHRASE,
+ /* Array of u8: len = NAN_MAX_SERVICE_NAME_LEN 255 bytes */
+ QCA_WLAN_VENDOR_ATTR_NDP_SERVICE_NAME,
+ /* Unsigned 32-bit bitmap indicating schedule update
+ * BIT_0: NSS Update
+ * BIT_1: Channel list update
+ */
+ QCA_WLAN_VENDOR_ATTR_NDP_SCHEDULE_UPDATE_REASON,
+ /* Unsigned 32-bit value for NSS */
+ QCA_WLAN_VENDOR_ATTR_NDP_NSS,
+ /* Unsigned 32-bit value for NUMBER NDP CHANNEL */
+ QCA_WLAN_VENDOR_ATTR_NDP_NUM_CHANNELS,
+ /* Unsigned 32-bit value for CHANNEL BANDWIDTH
+ * 0:20 MHz, 1:40 MHz, 2:80 MHz, 3:160 MHz
+ */
+ QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_WIDTH,
+ /* Array of channel/band width */
+ QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_INFO,
+ /* IPv6 address used by NDP (in network byte order), 16 bytes array.
+ * This attribute is used and optional for ndp request, ndp response,
+ * ndp indication, and ndp confirm.
+ */
+ QCA_WLAN_VENDOR_ATTR_NDP_IPV6_ADDR = 27,
+ /* Unsigned 16-bit value indicating transport port used by NDP.
+ * This attribute is used and optional for ndp response, ndp indication,
+ * and ndp confirm.
+ */
+ QCA_WLAN_VENDOR_ATTR_NDP_TRANSPORT_PORT = 28,
+ /* Unsigned 8-bit value indicating protocol used by NDP and assigned by
+ * the Internet Assigned Numbers Authority (IANA) as per:
+ * https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml
+ * This attribute is used and optional for ndp response, ndp indication,
+ * and ndp confirm.
+ */
+ QCA_WLAN_VENDOR_ATTR_NDP_TRANSPORT_PROTOCOL = 29,
+ /* Unsigned 8-bit value indicating if NDP remote peer supports NAN NDPE.
+ * 1:support 0:not support
+ */
+ QCA_WLAN_VENDOR_ATTR_PEER_NDPE_SUPPORT = 30,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_MAX =
+ QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_AFTER_LAST - 1,
+};
+
+enum qca_wlan_ndp_sub_cmd {
+ QCA_WLAN_VENDOR_ATTR_NDP_INVALID = 0,
+ /* Command to create a NAN data path interface */
+ QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_CREATE = 1,
+ /* Command to delete a NAN data path interface */
+ QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_DELETE = 2,
+ /* Command to initiate a NAN data path session */
+ QCA_WLAN_VENDOR_ATTR_NDP_INITIATOR_REQUEST = 3,
+ /* Command to notify if the NAN data path session was sent */
+ QCA_WLAN_VENDOR_ATTR_NDP_INITIATOR_RESPONSE = 4,
+ /* Command to respond to NAN data path session */
+ QCA_WLAN_VENDOR_ATTR_NDP_RESPONDER_REQUEST = 5,
+ /* Command to notify on the responder about the response */
+ QCA_WLAN_VENDOR_ATTR_NDP_RESPONDER_RESPONSE = 6,
+ /* Command to initiate a NAN data path end */
+ QCA_WLAN_VENDOR_ATTR_NDP_END_REQUEST = 7,
+ /* Command to notify the if end request was sent */
+ QCA_WLAN_VENDOR_ATTR_NDP_END_RESPONSE = 8,
+ /* Command to notify the peer about the end request */
+ QCA_WLAN_VENDOR_ATTR_NDP_REQUEST_IND = 9,
+ /* Command to confirm the NAN data path session is complete */
+ QCA_WLAN_VENDOR_ATTR_NDP_CONFIRM_IND = 10,
+ /* Command to indicate the peer about the end request being received */
+ QCA_WLAN_VENDOR_ATTR_NDP_END_IND = 11,
+ /* Command to indicate the peer of schedule update */
+ QCA_WLAN_VENDOR_ATTR_NDP_SCHEDULE_UPDATE_IND = 12
+};
+
+/**
+ * enum qca_wlan_vendor_attr_nd_offload - Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD.
+ */
+enum qca_wlan_vendor_attr_nd_offload {
+ QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_INVALID = 0,
+ /* Flag to set Neighbour Discovery offload */
+ QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG,
+ /* Keep last */
+ QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX =
+ QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_AFTER_LAST - 1,
+};
+
+/**
+ * enum packet_filter_sub_cmd - Packet filter sub commands
+ */
+enum packet_filter_sub_cmd {
+ /**
+ * Write packet filter program and/or data. The driver/firmware should
+ * disable APF before writing into local buffer and re-enable APF after
+ * writing is done.
+ */
+ QCA_WLAN_SET_PACKET_FILTER = 1,
+ /* Get packet filter feature capabilities from driver */
+ QCA_WLAN_GET_PACKET_FILTER = 2,
+ /**
+ * Write packet filter program and/or data. User space will send the
+ * %QCA_WLAN_DISABLE_PACKET_FILTER command before issuing this command
+ * and will send the %QCA_WLAN_ENABLE_PACKET_FILTER afterwards. The key
+ * difference from that %QCA_WLAN_SET_PACKET_FILTER is the control over
+ * enable/disable is given to user space with this command. Also,
+ * user space sends the length of program portion in the buffer within
+ * %QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROG_LENGTH.
+ */
+ QCA_WLAN_WRITE_PACKET_FILTER = 3,
+ /* Read packet filter program and/or data */
+ QCA_WLAN_READ_PACKET_FILTER = 4,
+ /* Enable APF feature */
+ QCA_WLAN_ENABLE_PACKET_FILTER = 5,
+ /* Disable APF feature */
+ QCA_WLAN_DISABLE_PACKET_FILTER = 6,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_packet_filter - BPF control commands used by
+ * vendor QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER.
+ */
+enum qca_wlan_vendor_attr_packet_filter {
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID = 0,
+ /* Unsigned 32-bit enum passed using packet_filter_sub_cmd */
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
+ /* Unsigned 32-bit value indicating the packet filter version */
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION,
+ /* Unsigned 32-bit value indicating the packet filter id */
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID,
+ /**
+ * Unsigned 32-bit value indicating the packet filter size including
+ * program + data.
+ */
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE,
+ /* Unsigned 32-bit value indicating the packet filter current offset */
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
+ /* Program and/or data in bytes */
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM,
+ /* Unsigned 32-bit value of the length of the program section in packet
+ * filter buffer.
+ */
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROG_LENGTH = 7,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX =
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_drv_info - WLAN driver info used by vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE.
+ */
+enum qca_wlan_vendor_drv_info {
+ QCA_WLAN_VENDOR_ATTR_DRV_INFO_INVALID = 0,
+ /* Maximum Message size info between firmware & HOST
+ * Unsigned 32-bit value
+ */
+ QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_DRV_INFO_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_DRV_INFO_MAX =
+ QCA_WLAN_VENDOR_ATTR_DRV_INFO_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_wake_stats - Wake lock stats used by vendor
+ * command QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS.
+ */
+enum qca_wlan_vendor_attr_wake_stats {
+ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_INVALID = 0,
+ /* Unsigned 32-bit value indicating the total count of wake event */
+ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_CMD_EVENT_WAKE,
+ /* Array of individual wake count, each index representing wake reason
+ */
+ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_CMD_EVENT_WAKE_CNT_PTR,
+ /* Unsigned 32-bit value representing wake count array */
+ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_CMD_EVENT_WAKE_CNT_SZ,
+ /* Unsigned 32-bit total wake count value of driver/fw */
+ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_DRIVER_FW_LOCAL_WAKE,
+ /* Array of wake stats of driver/fw */
+ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_PTR,
+ /* Unsigned 32-bit total wake count value of driver/fw */
+ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_SZ,
+ /* Unsigned 32-bit total wake count value of packets received */
+ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_RX_DATA_WAKE,
+ /* Unsigned 32-bit wake count value unicast packets received */
+ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_UNICAST_CNT,
+ /* Unsigned 32-bit wake count value multicast packets received */
+ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_MULTICAST_CNT,
+ /* Unsigned 32-bit wake count value broadcast packets received */
+ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_BROADCAST_CNT,
+ /* Unsigned 32-bit wake count value of ICMP packets */
+ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP_PKT,
+ /* Unsigned 32-bit wake count value of ICMP6 packets */
+ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_PKT,
+ /* Unsigned 32-bit value ICMP6 router advertisement */
+ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_RA,
+ /* Unsigned 32-bit value ICMP6 neighbor advertisement */
+ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_NA,
+ /* Unsigned 32-bit value ICMP6 neighbor solicitation */
+ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_NS,
+ /* Unsigned 32-bit wake count value of receive side ICMP4 multicast */
+ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP4_RX_MULTICAST_CNT,
+ /* Unsigned 32-bit wake count value of receive side ICMP6 multicast */
+ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_RX_MULTICAST_CNT,
+ /* Unsigned 32-bit wake count value of receive side multicast */
+ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_OTHER_RX_MULTICAST_CNT,
+ /* Unsigned 32-bit wake count value of a given RSSI breach */
+ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RSSI_BREACH_CNT,
+ /* Unsigned 32-bit wake count value of low RSSI */
+ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_LOW_RSSI_CNT,
+ /* Unsigned 32-bit value GSCAN count */
+ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_GSCAN_CNT,
+ /* Unsigned 32-bit value PNO complete count */
+ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_PNO_COMPLETE_CNT,
+ /* Unsigned 32-bit value PNO match count */
+ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_PNO_MATCH_CNT,
+ /* keep last */
+ QCA_WLAN_VENDOR_GET_WAKE_STATS_AFTER_LAST,
+ QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX =
+ QCA_WLAN_VENDOR_GET_WAKE_STATS_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_thermal_cmd - Vendor subcmd attributes to set
+ * cmd value. Used for NL attributes for data used by
+ * QCA_NL80211_VENDOR_SUBCMD_THERMAL_CMD sub command.
+ */
+enum qca_wlan_vendor_attr_thermal_cmd {
+ QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_INVALID = 0,
+ /* The value of command, driver will implement different operations
+ * according to this value. It uses values defined in
+ * enum qca_wlan_vendor_attr_thermal_cmd_type.
+ * u32 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_VALUE = 1,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_MAX =
+ QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_AFTER_LAST - 1
+};
+
+/**
+ * qca_wlan_vendor_attr_thermal_cmd_type: Attribute values for
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_VALUE to the vendor subcmd
+ * QCA_NL80211_VENDOR_SUBCMD_THERMAL_CMD. This represents the
+ * thermal command types sent to driver.
+ * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_PARAMS: Request to
+ * get thermal shutdown configuration parameters for display. Parameters
+ * responded from driver are defined in
+ * enum qca_wlan_vendor_attr_get_thermal_params_rsp.
+ * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_TEMPERATURE: Request to
+ * get temperature. Host should respond with a temperature data. It is defined
+ * in enum qca_wlan_vendor_attr_thermal_get_temperature.
+ * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SUSPEND: Request to execute thermal
+ * suspend action.
+ * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_RESUME: Request to execute thermal
+ * resume action.
+ */
+enum qca_wlan_vendor_attr_thermal_cmd_type {
+ QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_PARAMS,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_TEMPERATURE,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SUSPEND,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_RESUME,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_thermal_get_temperature - vendor subcmd attributes
+ * to get chip temperature by user.
+ * enum values are used for NL attributes for data used by
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_TEMPERATURE command for data used
+ * by QCA_NL80211_VENDOR_SUBCMD_THERMAL_CMD sub command.
+ */
+enum qca_wlan_vendor_attr_thermal_get_temperature {
+ QCA_WLAN_VENDOR_ATTR_THERMAL_GET_TEMPERATURE_INVALID = 0,
+ /* Temperature value (degree Celsius) from driver.
+ * u32 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_THERMAL_GET_TEMPERATURE_DATA,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_THERMAL_GET_TEMPERATURE_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_GET_TEMPERATURE_MAX =
+ QCA_WLAN_VENDOR_ATTR_THERMAL_GET_TEMPERATURE_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_get_thermal_params_rsp - vendor subcmd attributes
+ * to get configuration parameters of thermal shutdown feature. Enum values are
+ * used by QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_PARAMS command for data
+ * used by QCA_NL80211_VENDOR_SUBCMD_THERMAL_CMD sub command.
+ */
+enum qca_wlan_vendor_attr_get_thermal_params_rsp {
+ QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_INVALID = 0,
+ /* Indicate if the thermal shutdown feature is enabled.
+ * NLA_FLAG attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_SHUTDOWN_EN,
+ /* Indicate if the auto mode is enabled.
+ * Enable: Driver triggers the suspend/resume action.
+ * Disable: User space triggers the suspend/resume action.
+ * NLA_FLAG attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_SHUTDOWN_AUTO_EN,
+ /* Thermal resume threshold (degree Celsius). Issue the resume command
+ * if the temperature value is lower than this threshold.
+ * u16 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_RESUME_THRESH,
+ /* Thermal warning threshold (degree Celsius). FW reports temperature
+ * to driver if it's higher than this threshold.
+ * u16 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_WARNING_THRESH,
+ /* Thermal suspend threshold (degree Celsius). Issue the suspend command
+ * if the temperature value is higher than this threshold.
+ * u16 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_SUSPEND_THRESH,
+ /* FW reports temperature data periodically at this interval (ms).
+ * u16 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_SAMPLE_RATE,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_MAX =
+ QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_thermal_event - vendor subcmd attributes to
+ * report thermal events from driver to user space.
+ * enum values are used for NL attributes for data used by
+ * QCA_NL80211_VENDOR_SUBCMD_THERMAL_EVENT sub command.
+ */
+enum qca_wlan_vendor_attr_thermal_event {
+ QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_INVALID = 0,
+ /* Temperature value (degree Celsius) from driver.
+ * u32 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_TEMPERATURE,
+ /* Indication of resume completion from power save mode.
+ * NLA_FLAG attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_RESUME_COMPLETE,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_MAX =
+ QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_AFTER_LAST - 1,
+};
+
+/**
+ * enum he_fragmentation_val - HE fragmentation support values
+ * Indicates level of dynamic fragmentation that is supported by
+ * a STA as a recipient.
+ * HE fragmentation values are defined in IEEE P802.11ax/D2.0, 9.4.2.237.2
+ * (HE MAC Capabilities Information field) and are used in HE Capabilities
+ * element to advertise the support. These values are validated in the driver
+ * to check the device capability and advertised in the HE Capabilities
+ * element. These values are used to configure testbed device to allow the
+ * advertised hardware capabilities to be downgraded for testing purposes.
+ *
+ * @HE_FRAG_DISABLE: no support for dynamic fragmentation
+ * @HE_FRAG_LEVEL1: support for dynamic fragments that are
+ * contained within an MPDU or S-MPDU, no support for dynamic fragments
+ * within an A-MPDU that is not an S-MPDU.
+ * @HE_FRAG_LEVEL2: support for dynamic fragments that are
+ * contained within an MPDU or S-MPDU and support for up to one dynamic
+ * fragment for each MSDU, each A-MSDU if supported by the recipient, and
+ * each MMPDU within an A-MPDU or multi-TID A-MPDU that is not an
+ * MPDU or S-MPDU.
+ * @HE_FRAG_LEVEL3: support for dynamic fragments that are
+ * contained within an MPDU or S-MPDU and support for multiple dynamic
+ * fragments for each MSDU and for each A-MSDU if supported by the
+ * recipient within an A-MPDU or multi-TID AMPDU and up to one dynamic
+ * fragment for each MMPDU in a multi-TID A-MPDU that is not an S-MPDU.
+ */
+enum he_fragmentation_val {
+ HE_FRAG_DISABLE,
+ HE_FRAG_LEVEL1,
+ HE_FRAG_LEVEL2,
+ HE_FRAG_LEVEL3,
+};
+
+/**
+ * enum he_mcs_config - HE MCS support configuration
+ *
+ * Configures the HE Tx/Rx MCS map in HE capability IE for given bandwidth.
+ * These values are used in driver to configure the HE MCS map to advertise
+ * Tx/Rx MCS map in HE capability and these values are applied for all the
+ * streams supported by the device. To configure MCS for different bandwidths,
+ * vendor command needs to be sent using this attribute with appropriate value.
+ * For example, to configure HE_80_MCS_0_7, send vendor command using HE MCS
+ * attribute with HE_80_MCS0_7. And to configure HE MCS for HE_160_MCS0_11
+ * send this command using HE MCS config attribute with value HE_160_MCS0_11.
+ * These values are used to configure testbed device to allow the advertised
+ * hardware capabilities to be downgraded for testing purposes. The enum values
+ * are defined such that BIT[1:0] indicates the MCS map value. Values 3,7 and
+ * 11 are not used as BIT[1:0] value is 3 which is used to disable MCS map.
+ * These values are validated in the driver before setting the MCS map and
+ * driver returns error if the input is other than these enum values.
+ *
+ * @HE_80_MCS0_7: support for HE 80/40/20 MHz MCS 0 to 7
+ * @HE_80_MCS0_9: support for HE 80/40/20 MHz MCS 0 to 9
+ * @HE_80_MCS0_11: support for HE 80/40/20 MHz MCS 0 to 11
+ * @HE_160_MCS0_7: support for HE 160 MHz MCS 0 to 7
+ * @HE_160_MCS0_9: support for HE 160 MHz MCS 0 to 9
+ * @HE_160_MCS0_11: support for HE 160 MHz MCS 0 to 11
+ * @HE_80P80_MCS0_7: support for HE 80p80 MHz MCS 0 to 7
+ * @HE_80P80_MCS0_9: support for HE 80p80 MHz MCS 0 to 9
+ * @HE_80P80_MCS0_11: support for HE 80p80 MHz MCS 0 to 11
+ */
+enum he_mcs_config {
+ HE_80_MCS0_7 = 0,
+ HE_80_MCS0_9 = 1,
+ HE_80_MCS0_11 = 2,
+ HE_160_MCS0_7 = 4,
+ HE_160_MCS0_9 = 5,
+ HE_160_MCS0_11 = 6,
+ HE_80P80_MCS0_7 = 8,
+ HE_80P80_MCS0_9 = 9,
+ HE_80P80_MCS0_11 = 10,
+};
+
+/**
+ * enum qca_wlan_ba_session_config - BA session configuration
+ *
+ * Indicates the configuration values for BA session configuration attribute.
+ *
+ * @QCA_WLAN_ADD_BA: Establish a new BA session with given configuration.
+ * @QCA_WLAN_DELETE_BA: Delete the existing BA session for given TID.
+ */
+enum qca_wlan_ba_session_config {
+ QCA_WLAN_ADD_BA = 1,
+ QCA_WLAN_DELETE_BA = 2,
+};
+
+/**
+ * enum qca_wlan_ac_type - Access category type
+ *
+ * Indicates the access category type value.
+ *
+ * @QCA_WLAN_AC_BE: BE access category
+ * @QCA_WLAN_AC_BK: BK access category
+ * @QCA_WLAN_AC_VI: VI access category
+ * @QCA_WLAN_AC_VO: VO access category
+ * @QCA_WLAN_AC_ALL: All ACs
+ */
+enum qca_wlan_ac_type {
+ QCA_WLAN_AC_BE = 0,
+ QCA_WLAN_AC_BK = 1,
+ QCA_WLAN_AC_VI = 2,
+ QCA_WLAN_AC_VO = 3,
+ QCA_WLAN_AC_ALL = 4,
+};
+
+/**
+ * enum qca_wlan_he_ltf_cfg - HE LTF configuration
+ *
+ * Indicates the HE LTF configuration value.
+ *
+ * @QCA_WLAN_HE_LTF_AUTO: HE-LTF is automatically set to the mandatory HE-LTF,
+ * based on the GI setting
+ * @QCA_WLAN_HE_LTF_1X: 1X HE LTF is 3.2us LTF
+ * @QCA_WLAN_HE_LTF_2X: 2X HE LTF is 6.4us LTF
+ * @QCA_WLAN_HE_LTF_4X: 4X HE LTF is 12.8us LTF
+ */
+enum qca_wlan_he_ltf_cfg {
+ QCA_WLAN_HE_LTF_AUTO = 0,
+ QCA_WLAN_HE_LTF_1X = 1,
+ QCA_WLAN_HE_LTF_2X = 2,
+ QCA_WLAN_HE_LTF_4X = 3,
+};
+
+/**
+ * enum qca_wlan_he_mac_padding_dur - HE trigger frame MAC padding duration
+ *
+ * Indicates the HE trigger frame MAC padding duration value.
+ *
+ * @QCA_WLAN_HE_NO_ADDITIONAL_PROCESS_TIME: no additional time required to
+ * process the trigger frame.
+ * @QCA_WLAN_HE_8US_OF_PROCESS_TIME: indicates the 8us of processing time for
+ * trigger frame.
+ * @QCA_WLAN_HE_16US_OF_PROCESS_TIME: indicates the 16us of processing time for
+ * trigger frame.
+ */
+enum qca_wlan_he_mac_padding_dur {
+ QCA_WLAN_HE_NO_ADDITIONAL_PROCESS_TIME = 0,
+ QCA_WLAN_HE_8US_OF_PROCESS_TIME = 1,
+ QCA_WLAN_HE_16US_OF_PROCESS_TIME = 2,
+};
+
+/**
+ * enum qca_wlan_he_om_ctrl_ch_bw - HE OM control field BW configuration
+ *
+ * Indicates the HE Operating mode control channel width setting value.
+ *
+ * @QCA_WLAN_HE_OM_CTRL_BW_20M: Primary 20 MHz
+ * @QCA_WLAN_HE_OM_CTRL_BW_40M: Primary 40 MHz
+ * @QCA_WLAN_HE_OM_CTRL_BW_80M: Primary 80 MHz
+ * @QCA_WLAN_HE_OM_CTRL_BW_160M: 160 MHz and 80+80 MHz
+ */
+enum qca_wlan_he_om_ctrl_ch_bw {
+ QCA_WLAN_HE_OM_CTRL_BW_20M = 0,
+ QCA_WLAN_HE_OM_CTRL_BW_40M = 1,
+ QCA_WLAN_HE_OM_CTRL_BW_80M = 2,
+ QCA_WLAN_HE_OM_CTRL_BW_160M = 3,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_he_omi_tx: Represents attributes for
+ * HE operating mode control transmit request. These attributes are
+ * sent as part of QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OMI_TX and
+ * QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_HE_OMI_RX_NSS: Mandatory 8-bit unsigned value
+ * indicates the maximum number of spatial streams, NSS, that the STA
+ * supports in reception for PPDU bandwidths less than or equal to 80 MHz
+ * and is set to NSS - 1.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_HE_OMI_CH_BW: Mandatory 8-bit unsigned value
+ * indicates the operating channel width supported by the STA for both
+ * reception and transmission. Uses enum qca_wlan_he_om_ctrl_ch_bw values.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DISABLE: Mandatory 8-bit unsigned value
+ * indicates the all trigger based UL MU operations by the STA.
+ * 0 - UL MU operations are enabled by the STA.
+ * 1 - All triggered UL MU transmissions are suspended by the STA.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_HE_OMI_TX_NSTS: Mandatory 8-bit unsigned value
+ * indicates the maximum number of space-time streams, NSTS, that
+ * the STA supports in transmission and is set to NSTS - 1.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DATA_DISABLE: 8-bit unsigned value
+ * combined with the UL MU Disable subfield and the recipient's setting
+ * of the OM Control UL MU Data Disable RX Support subfield in the HE MAC
+ * capabilities to determine which HE TB PPDUs are possible by the
+ * STA to transmit.
+ * 0 - UL MU data operations are enabled by the STA.
+ * 1 - Determine which HE TB PPDU types are allowed by the STA if UL MU disable
+ * bit is not set, else UL MU Tx is suspended.
+ *
+ */
+enum qca_wlan_vendor_attr_he_omi_tx {
+ QCA_WLAN_VENDOR_ATTR_HE_OMI_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_HE_OMI_RX_NSS = 1,
+ QCA_WLAN_VENDOR_ATTR_HE_OMI_CH_BW = 2,
+ QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DISABLE = 3,
+ QCA_WLAN_VENDOR_ATTR_HE_OMI_TX_NSTS = 4,
+ QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DATA_DISABLE = 5,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_HE_OMI_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_HE_OMI_MAX =
+ QCA_WLAN_VENDOR_ATTR_HE_OMI_AFTER_LAST - 1,
+};
+
+/* Attributes for data used by
+ * QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION
+ */
+enum qca_wlan_vendor_attr_wifi_test_config {
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_INVALID = 0,
+ /* 8-bit unsigned value to configure the driver to enable/disable
+ * WMM feature. This attribute is used to configure testbed device.
+ * 1-enable, 0-disable
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE = 1,
+
+ /* 8-bit unsigned value to configure the driver to accept/reject
+ * the addba request from peer. This attribute is used to configure
+ * the testbed device.
+ * 1-accept addba, 0-reject addba
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ = 2,
+
+ /* 8-bit unsigned value to configure the driver to send or not to
+ * send the addba request to peer.
+ * This attribute is used to configure the testbed device.
+ * 1-send addba, 0-do not send addba
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ = 3,
+
+ /* 8-bit unsigned value to indicate the HE fragmentation support.
+ * Uses enum he_fragmentation_val values.
+ * This attribute is used to configure the testbed device to
+ * allow the advertised hardware capabilities to be downgraded
+ * for testing purposes.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION = 4,
+
+ /* 8-bit unsigned value to indicate the HE MCS support.
+ * Uses enum he_mcs_config values.
+ * This attribute is used to configure the testbed device to
+ * allow the advertised hardware capabilities to be downgraded
+ * for testing purposes.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS = 5,
+
+ /* 8-bit unsigned value to configure the driver to allow or not to
+ * allow the connection with WEP/TKIP in HT/VHT/HE modes.
+ * This attribute is used to configure the testbed device.
+ * 1-allow WEP/TKIP in HT/VHT/HE, 0-do not allow WEP/TKIP.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE = 6,
+
+ /* 8-bit unsigned value to configure the driver to add a
+ * new BA session or delete the existing BA session for
+ * given TID. ADDBA command uses the buffer size and TID
+ * configuration if user specifies the values else default
+ * value for buffer size is used for all TIDs if the TID
+ * also not specified. For DEL_BA command TID value is
+ * required to process the command.
+ * Uses enum qca_wlan_ba_session_config values.
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION = 7,
+
+ /* 16-bit unsigned value to configure the buffer size in addba
+ * request and response frames.
+ * This attribute is used to configure the testbed device.
+ * The range of the value is 0 to 256.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE = 8,
+
+ /* 8-bit unsigned value to configure the buffer size in addba
+ * request and response frames.
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID = 9,
+
+ /* 8-bit unsigned value to configure the no ack policy.
+ * To configure no ack policy, access category value is
+ * required to process the command.
+ * This attribute is used to configure the testbed device.
+ * 1 - enable no ack, 0 - disable no ack.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK = 10,
+
+ /* 8-bit unsigned value to configure the AC for no ack policy
+ * This attribute is used to configure the testbed device.
+ * Uses the enum qca_wlan_ac_type values.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC = 11,
+
+ /* 8-bit unsigned value to configure the HE LTF
+ * This attribute is used to configure the testbed device.
+ * Uses the enum qca_wlan_he_ltf_cfg values.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_LTF = 12,
+
+ /* 8-bit unsigned value to configure the tx beamformee.
+ * This attribute is used to configure the testbed device.
+ * 1-enable, 0-disable.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_TX_BEAMFORMEE = 13,
+
+ /* 8-bit unsigned value to configure the tx beamformee number
+ * of space-time streams.
+ * This attribute is used to configure the testbed device.
+ * The range of the value is 0 to 8.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_BEAMFORMEE_NSTS = 14,
+
+ /* 8-bit unsigned value to configure the MU EDCA params for given AC
+ * This attribute is used to configure the testbed device.
+ * Uses the enum qca_wlan_ac_type values.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MU_EDCA_AC = 15,
+
+ /* 8-bit unsigned value to configure the MU EDCA AIFSN for given AC
+ * To configure MU EDCA AIFSN value, MU EDCA access category value
+ * is required to process the command.
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MU_EDCA_AIFSN = 16,
+
+ /* 8-bit unsigned value to configure the MU EDCA ECW min value for
+ * given AC.
+ * To configure MU EDCA ECW min value, MU EDCA access category value
+ * is required to process the command.
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MU_EDCA_ECWMIN = 17,
+
+ /* 8-bit unsigned value to configure the MU EDCA ECW max value for
+ * given AC.
+ * To configure MU EDCA ECW max value, MU EDCA access category value
+ * is required to process the command.
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MU_EDCA_ECWMAX = 18,
+
+ /* 8-bit unsigned value to configure the MU EDCA timer for given AC
+ * To configure MU EDCA timer value, MU EDCA access category value
+ * is required to process the command.
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MU_EDCA_TIMER = 19,
+
+ /* 8-bit unsigned value to configure the HE trigger frame MAC padding
+ * duration.
+ * This attribute is used to configure the testbed device.
+ * Uses the enum qca_wlan_he_mac_padding_dur values.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MAC_PADDING_DUR = 20,
+
+ /* 8-bit unsigned value to override the MU EDCA params to defaults
+ * regardless of the AP beacon MU EDCA params. If it is enabled use
+ * the default values else use the MU EDCA params from AP beacon.
+ * This attribute is used to configure the testbed device.
+ * 1-enable, 0-disable.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OVERRIDE_MU_EDCA = 21,
+
+ /* 8-bit unsigned value to configure the support for receiving
+ * an MPDU that contains an operating mode control subfield.
+ * This attribute is used to configure the testbed device.
+ * 1-enable, 0-disable.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_SUPP = 22,
+
+ /* Nested attribute values required to setup the TWT session.
+ * enum qca_wlan_vendor_attr_twt_setup provides the necessary
+ * information to set up the session. It contains broadcast flags,
+ * set_up flags, trigger value, flow type, flow ID, wake interval
+ * exponent, protection, target wake time, wake duration, wake interval
+ * mantissa. These nested attributes are used to setup a host triggered
+ * TWT session.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP = 23,
+
+ /* This nested attribute is used to terminate the current TWT session.
+ * It does not currently carry any attributes.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_TERMINATE = 24,
+
+ /* This nested attribute is used to suspend the current TWT session.
+ * It does not currently carry any attributes.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SUSPEND = 25,
+
+ /* Nested attribute values to indicate the request for resume.
+ * This attribute is used to resume the TWT session.
+ * enum qca_wlan_vendor_attr_twt_resume provides the necessary
+ * parameters required to resume the TWT session.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_RESUME = 26,
+
+ /* 8-bit unsigned value to set the HE operating mode control
+ * (OM CTRL) Channel Width subfield.
+ * The Channel Width subfield indicates the operating channel width
+ * supported by the STA for both reception and transmission.
+ * Uses the enum qca_wlan_he_om_ctrl_ch_bw values.
+ * This setting is cleared with the
+ * QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_CLEAR_HE_OM_CTRL_CONFIG
+ * flag attribute to reset defaults.
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_BW = 27,
+
+ /* 8-bit unsigned value to configure the number of spatial
+ * streams in HE operating mode control field.
+ * This setting is cleared with the
+ * QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_CLEAR_HE_OM_CTRL_CONFIG
+ * flag attribute to reset defaults.
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_NSS = 28,
+
+ /* Flag attribute to configure the UL MU disable bit in
+ * HE operating mode control field.
+ * This setting is cleared with the
+ * QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_CLEAR_HE_OM_CTRL_CONFIG
+ * flag attribute to reset defaults.
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_UL_MU_DISABLE = 29,
+
+ /* Flag attribute to clear the previously set HE operating mode
+ * control field configuration.
+ * This attribute is used to configure the testbed device to reset
+ * defaults to clear any previously set HE operating mode control
+ * field configuration.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_CLEAR_HE_OM_CTRL_CONFIG = 30,
+
+ /* 8-bit unsigned value to configure HE single user PPDU
+ * transmission. By default this setting is disabled and it
+ * is disabled in the reset defaults of the device configuration.
+ * This attribute is used to configure the testbed device.
+ * 1-enable, 0-disable
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_SUPPDU = 31,
+
+ /* 8-bit unsigned value to configure action frame transmission
+ * in HE trigger based PPDU transmission.
+ * By default this setting is disabled and it is disabled in
+ * the reset defaults of the device configuration.
+ * This attribute is used to configure the testbed device.
+ * 1-enable, 0-disable
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_ACTION_TX_TB_PPDU = 32,
+
+ /* Nested attribute to indicate HE operating mode control field
+ * transmission. It contains operating mode control field Nss,
+ * channel bandwidth, Tx Nsts and UL MU disable attributes.
+ * These nested attributes are used to send HE operating mode control
+ * with configured values.
+ * Uses the enum qca_wlan_vendor_attr_he_omi_tx attributes.
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OMI_TX = 33,
+
+ /* 8-bit unsigned value to configure +HTC_HE support to indicate the
+ * support for the reception of a frame that carries an HE variant
+ * HT Control field.
+ * This attribute is used to configure the testbed device.
+ * 1-enable, 0-disable
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_HTC_HE_SUPP = 34,
+
+ /* 8-bit unsigned value to configure VHT support in 2.4G band.
+ * This attribute is used to configure the testbed device.
+ * 1-enable, 0-disable
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_2G_VHT = 35,
+
+ /* 8-bit unsigned value to configure HE testbed defaults.
+ * This attribute is used to configure the testbed device.
+ * 1-set the device HE capabilities to testbed defaults.
+ * 0-reset the device HE capabilities to supported config.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SET_HE_TESTBED_DEFAULTS = 36,
+
+ /* 8-bit unsigned value to configure TWT request support.
+ * This attribute is used to configure the testbed device.
+ * 1-enable, 0-disable.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TWT_REQ_SUPPORT = 37,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX =
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_bss_filter - Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER.
+ * The user can add/delete the filter by specifying the BSSID/STA MAC address in
+ * QCA_WLAN_VENDOR_ATTR_BSS_FILTER_MAC_ADDR, filter type in
+ * QCA_WLAN_VENDOR_ATTR_BSS_FILTER_TYPE, add/delete action in
+ * QCA_WLAN_VENDOR_ATTR_BSS_FILTER_ACTION in the request. The user can get the
+ * statistics of an unassociated station by specifying the MAC address in
+ * QCA_WLAN_VENDOR_ATTR_BSS_FILTER_MAC_ADDR, station type in
+ * QCA_WLAN_VENDOR_ATTR_BSS_FILTER_TYPE, GET action in
+ * QCA_WLAN_VENDOR_ATTR_BSS_FILTER_ACTION in the request. The user also can get
+ * the statistics of all unassociated stations by specifying the Broadcast MAC
+ * address (ff:ff:ff:ff:ff:ff) in QCA_WLAN_VENDOR_ATTR_BSS_FILTER_MAC_ADDR with
+ * above procedure. In the response, driver shall specify statistics
+ * information nested in QCA_WLAN_VENDOR_ATTR_BSS_FILTER_STA_STATS.
+ */
+enum qca_wlan_vendor_attr_bss_filter {
+ QCA_WLAN_VENDOR_ATTR_BSS_FILTER_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_BSS_FILTER_MAC_ADDR = 1,
+ /* Other BSS filter type, unsigned 8 bit value. One of the values
+ * in enum qca_wlan_vendor_bss_filter_type.
+ */
+ QCA_WLAN_VENDOR_ATTR_BSS_FILTER_TYPE = 2,
+ /* Other BSS filter action, unsigned 8 bit value. One of the values
+ * in enum qca_wlan_vendor_bss_filter_action.
+ */
+ QCA_WLAN_VENDOR_ATTR_BSS_FILTER_ACTION = 3,
+ /* Array of nested attributes where each entry is the statistics
+ * information of the specified station that belong to another BSS.
+ * Attributes for each entry are taken from enum
+ * qca_wlan_vendor_bss_filter_sta_stats.
+ * Other BSS station configured in
+ * QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER with filter type
+ * QCA_WLAN_VENDOR_BSS_FILTER_TYPE_STA.
+ * Statistics returned by QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER
+ * with filter action QCA_WLAN_VENDOR_BSS_FILTER_ACTION_GET.
+ */
+ QCA_WLAN_VENDOR_ATTR_BSS_FILTER_STA_STATS = 4,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_BSS_FILTER_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_BSS_FILTER_MAX =
+ QCA_WLAN_VENDOR_ATTR_BSS_FILTER_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_bss_filter_type - Type of
+ * filter used in other BSS filter operations. Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER.
+ *
+ * @QCA_WLAN_VENDOR_BSS_FILTER_TYPE_BSSID: BSSID filter
+ * @QCA_WLAN_VENDOR_BSS_FILTER_TYPE_STA: Station MAC address filter
+ */
+enum qca_wlan_vendor_bss_filter_type {
+ QCA_WLAN_VENDOR_BSS_FILTER_TYPE_BSSID,
+ QCA_WLAN_VENDOR_BSS_FILTER_TYPE_STA,
+};
+
+/**
+ * enum qca_wlan_vendor_bss_filter_action - Type of
+ * action in other BSS filter operations. Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER.
+ *
+ * @QCA_WLAN_VENDOR_BSS_FILTER_ACTION_ADD: Add filter
+ * @QCA_WLAN_VENDOR_BSS_FILTER_ACTION_DEL: Delete filter
+ * @QCA_WLAN_VENDOR_BSS_FILTER_ACTION_GET: Get the statistics
+ */
+enum qca_wlan_vendor_bss_filter_action {
+ QCA_WLAN_VENDOR_BSS_FILTER_ACTION_ADD,
+ QCA_WLAN_VENDOR_BSS_FILTER_ACTION_DEL,
+ QCA_WLAN_VENDOR_BSS_FILTER_ACTION_GET,
+};
+
+/**
+ * enum qca_wlan_vendor_bss_filter_sta_stats - Attributes for
+ * the statistics of a specific unassociated station belonging to another BSS.
+ * The statistics provides information of the unassociated station
+ * filtered by other BSS operation - such as MAC, signal value.
+ * Used by the vendor command QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER.
+ *
+ * @QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_MAC: MAC address of the station.
+ * @QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_RSSI: Last received signal strength
+ * of the station. Unsigned 8 bit number containing RSSI.
+ * @QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_RSSI_TS: Time stamp of the host
+ * driver for the last received RSSI. Unsigned 64 bit number containing
+ * nanoseconds from the boottime.
+ */
+enum qca_wlan_vendor_bss_filter_sta_stats {
+ QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_INVALID = 0,
+ QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_MAC = 1,
+ QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_RSSI = 2,
+ QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_RSSI_TS = 3,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_AFTER_LAST,
+ QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_MAX =
+ QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_AFTER_LAST - 1
+};
+
+/* enum qca_wlan_nan_subcmd_type - Type of NAN command used by attribute
+ * QCA_WLAN_VENDOR_ATTR_NAN_SUBCMD_TYPE as a part of vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_NAN_EXT.
+ */
+enum qca_wlan_nan_ext_subcmd_type {
+ /* Subcmd of type NAN Enable Request */
+ QCA_WLAN_NAN_EXT_SUBCMD_TYPE_ENABLE_REQ = 1,
+ /* Subcmd of type NAN Disable Request */
+ QCA_WLAN_NAN_EXT_SUBCMD_TYPE_DISABLE_REQ = 2,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_nan_params - Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_NAN_EXT.
+ */
+enum qca_wlan_vendor_attr_nan_params {
+ QCA_WLAN_VENDOR_ATTR_NAN_INVALID = 0,
+ /* Carries NAN command for firmware component. Every vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_NAN_EXT must contain this attribute with a
+ * payload containing the NAN command. NLA_BINARY attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA = 1,
+ /* Indicates the type of NAN command sent with
+ * QCA_NL80211_VENDOR_SUBCMD_NAN_EXT. enum qca_wlan_nan_ext_subcmd_type
+ * describes the possible range of values. This attribute is mandatory
+ * if the command being issued is either
+ * QCA_WLAN_NAN_EXT_SUBCMD_TYPE_ENABLE_REQ or
+ * QCA_WLAN_NAN_EXT_SUBCMD_TYPE_DISABLE_REQ. NLA_U32 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_NAN_SUBCMD_TYPE = 2,
+ /* Frequency (in MHz) of primary NAN discovery social channel in 2.4 GHz
+ * band. This attribute is mandatory when command type is
+ * QCA_WLAN_NAN_EXT_SUBCMD_TYPE_ENABLE_REQ. NLA_U32 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_NAN_DISC_24GHZ_BAND_FREQ = 3,
+ /* Frequency (in MHz) of secondary NAN discovery social channel in 5 GHz
+ * band. This attribute is optional and should be included when command
+ * type is QCA_WLAN_NAN_EXT_SUBCMD_TYPE_ENABLE_REQ and NAN discovery
+ * has to be started on 5GHz along with 2.4GHz. NLA_U32 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_NAN_DISC_5GHZ_BAND_FREQ = 4,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_NAN_PARAMS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_NAN_PARAMS_MAX =
+ QCA_WLAN_VENDOR_ATTR_NAN_PARAMS_AFTER_LAST - 1
+};
+
+/**
+ * enum qca_wlan_vendor_attr_twt_setup: Represents attributes for
+ * TWT (Target Wake Time) setup request. These attributes are sent as part of
+ * %QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP and
+ * %QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST: Flag attribute.
+ * Disable (flag attribute not present) - Individual TWT
+ * Enable (flag attribute present) - Broadcast TWT.
+ * Individual means the session is between the STA and the AP.
+ * This session is established using a separate negotiation between
+ * STA and AP.
+ * Broadcast means the session is across multiple STAs and an AP. The
+ * configuration parameters are announced in Beacon frames by the AP.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_REQ_TYPE: Required (u8).
+ * Unsigned 8-bit qca_wlan_vendor_twt_setup_req_type to
+ * specify the TWT request type
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TRIGGER: Flag attribute
+ * Enable (flag attribute present) - TWT with trigger support.
+ * Disable (flag attribute not present) - TWT without trigger support.
+ * Trigger means the AP will send the trigger frame to allow STA to send data.
+ * Without trigger, the STA will wait for the MU EDCA timer before
+ * transmitting the data.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_TYPE: Required (u8)
+ * 0 - Announced TWT - In this mode, STA may skip few service periods to
+ * save more power. If STA wants to wake up, it will send a PS-POLL/QoS
+ * NULL frame to AP.
+ * 1 - Unannounced TWT - The STA will wakeup during every SP.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_ID: Optional (u8)
+ * Flow ID is the unique identifier for each TWT session.
+ * Currently this is not required and dialog ID will be set to zero.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_EXP: Required (u8)
+ * This attribute (exp) is used along with the mantissa to derive the
+ * wake interval using the following formula:
+ * pow(2,exp) = wake_intvl_us/wake_intvl_mantis
+ * Wake interval is the interval between 2 successive SP.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_PROTECTION: Flag attribute
+ * Enable (flag attribute present) - Protection required.
+ * Disable (flag attribute not present) - Protection not required.
+ * If protection is enabled, then the AP will use protection
+ * mechanism using RTS/CTS to self to reserve the airtime.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME: Optional (u32)
+ * This attribute is used as the SP offset which is the offset from
+ * TSF after which the wake happens. The units are in microseconds. If
+ * this attribute is not provided, then the value will be set to zero.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_DURATION: Required (u32)
+ * This is the duration of the service period. The units are in TU.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA: Required (u32)
+ * This attribute is used to configure wake interval mantissa.
+ * The units are in TU.
+ */
+enum qca_wlan_vendor_attr_twt_setup {
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST = 1,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_REQ_TYPE = 2,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TRIGGER = 3,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_TYPE = 4,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_ID = 5,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_EXP = 6,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_PROTECTION = 7,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME = 8,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_DURATION = 9,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA = 10,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX =
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_twt_resume: Represents attributes for
+ * TWT (Target Wake Time) resume request. These attributes are sent as part of
+ * %QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_RESUME and
+ * %QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT_TWT: Optional (u8)
+ * This attribute is used as the SP offset which is the offset from
+ * TSF after which the wake happens. The units are in microseconds.
+ * If this attribute is not provided, then the value will be set to
+ * zero.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT_TWT_SIZE: Required (u32)
+ * This attribute represents the next TWT subfield size.
+ */
+enum qca_wlan_vendor_attr_twt_resume {
+ QCA_WLAN_VENDOR_ATTR_TWT_RESUME_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT_TWT = 1,
+ QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT_TWT_SIZE = 2,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_TWT_RESUME_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_TWT_RESUME_MAX =
+ QCA_WLAN_VENDOR_ATTR_TWT_RESUME_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_twt_setup_req_type - Required (u8)
+ * Represents the setup type being requested for TWT.
+ * @QCA_WLAN_VENDOR_TWT_SETUP_REQUEST: STA is not specifying all the TWT
+ * parameters but relying on AP to fill the parameters during the negotiation.
+ * @QCA_WLAN_VENDOR_TWT_SETUP_SUGGEST: STA will provide all the suggested
+ * values which the AP may accept or AP may provide alternative parameters
+ * which the STA may accept.
+ * @QCA_WLAN_VENDOR_TWT_SETUP_DEMAND: STA is not willing to accept any
+ * alternate parameters than the requested ones.
+ */
+enum qca_wlan_vendor_twt_setup_req_type {
+ QCA_WLAN_VENDOR_TWT_SETUP_REQUEST = 1,
+ QCA_WLAN_VENDOR_TWT_SETUP_SUGGEST = 2,
+ QCA_WLAN_VENDOR_TWT_SETUP_DEMAND = 3,
+};
+
+/**
+ * enum qca_wlan_roam_scan_event_type - Type of roam scan event
+ *
+ * Indicates the type of roam scan event sent by firmware/driver.
+ *
+ * @QCA_WLAN_ROAM_SCAN_TRIGGER_EVENT: Roam scan trigger event type.
+ * @QCA_WLAN_ROAM_SCAN_STOP_EVENT: Roam scan stopped event type.
+ */
+enum qca_wlan_roam_scan_event_type {
+ QCA_WLAN_ROAM_SCAN_TRIGGER_EVENT = 0,
+ QCA_WLAN_ROAM_SCAN_STOP_EVENT = 1,
+};
+
+/**
+ * enum qca_wlan_roam_scan_trigger_reason - Roam scan trigger reason
+ *
+ * Indicates the reason for triggering roam scan by firmware/driver.
+ *
+ * @QCA_WLAN_ROAM_SCAN_TRIGGER_REASON_LOW_RSSI: Due to low RSSI of current AP.
+ * @QCA_WLAN_ROAM_SCAN_TRIGGER_REASON_HIGH_PER: Due to high packet error rate.
+ */
+enum qca_wlan_roam_scan_trigger_reason {
+ QCA_WLAN_ROAM_SCAN_TRIGGER_REASON_LOW_RSSI = 0,
+ QCA_WLAN_ROAM_SCAN_TRIGGER_REASON_HIGH_PER = 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_roam_scan - Vendor subcmd attributes to report
+ * roam scan related details from driver/firmware to user space. enum values
+ * are used for NL attributes sent with
+ * %QCA_NL80211_VENDOR_SUBCMD_ROAM_SCAN_EVENT sub command.
+ */
+enum qca_wlan_vendor_attr_roam_scan {
+ QCA_WLAN_VENDOR_ATTR_ROAM_SCAN_INVALID = 0,
+ /* Encapsulates type of roam scan event being reported. enum
+ * qca_wlan_roam_scan_event_type describes the possible range of
+ * values. u32 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_ROAM_SCAN_EVENT_TYPE = 1,
+ /* Encapsulates reason for triggering roam scan. enum
+ * qca_wlan_roam_scan_trigger_reason describes the possible range of
+ * values. u32 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_ROAM_SCAN_TRIGGER_REASON = 2,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_ROAM_SCAN_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_ROAM_SCAN_MAX =
+ QCA_WLAN_VENDOR_ATTR_ROAM_SCAN_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_cfr_method - QCA vendor CFR methods used by
+ * attribute QCA_WLAN_VENDOR_ATTR_PEER_CFR_METHOD as part of vendor
+ * command QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG.
+ */
+enum qca_wlan_vendor_cfr_method {
+ /* CFR method using QOS Null frame */
+ QCA_WLAN_VENDOR_CFR_METHOD_QOS_NULL = 0,
+};
+
+/**
+ * enum qca_wlan_vendor_peer_cfr_capture_attr - Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG to configure peer
+ * Channel Frequency Response capture parameters and enable periodic CFR
+ * capture.
+ */
+enum qca_wlan_vendor_peer_cfr_capture_attr {
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_CAPTURE_INVALID = 0,
+ /* 6-byte MAC address of the peer.
+ * This attribute is mandatory.
+ */
+ QCA_WLAN_VENDOR_ATTR_CFR_PEER_MAC_ADDR = 1,
+ /* Enable peer CFR Capture, flag attribute.
+ * This attribute is mandatory to enable peer CFR capture.
+ * If this attribute is not present, peer CFR capture is disabled.
+ */
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE = 2,
+ /* BW of measurement, attribute uses the values in enum nl80211_chan_width
+ * Supported values: 20, 40, 80, 80+80, 160.
+ * Note that all targets may not support all bandwidths.
+ * u8 attribute. This attribute is mandatory if attribute
+ * QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE is used.
+ */
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_BANDWIDTH = 3,
+ /* Periodicity of CFR measurement in msec.
+ * Periodicity should be a multiple of Base timer.
+ * Current Base timer value supported is 10 msecs (default).
+ * 0 for one shot capture. u32 attribute.
+ * This attribute is mandatory if attribute
+ * QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE is used.
+ */
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_PERIODICITY = 4,
+ /* Method used to capture Channel Frequency Response.
+ * Attribute uses the values defined in enum qca_wlan_vendor_cfr_method.
+ * u8 attribute. This attribute is mandatory if attribute
+ * QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE is used.
+ */
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_METHOD = 5,
+ /* Enable periodic CFR capture, flag attribute.
+ * This attribute is mandatory to enable Periodic CFR capture.
+ * If this attribute is not present, periodic CFR capture is disabled.
+ */
+ QCA_WLAN_VENDOR_ATTR_PERIODIC_CFR_CAPTURE_ENABLE = 6,
+
+ /* Keep last */
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_MAX =
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_throughput_level - Current throughput level
+ *
+ * Indicates the current level of throughput calculated by the driver. The
+ * driver may choose different thresholds to decide whether the throughput level
+ * is low or medium or high based on variety of parameters like physical link
+ * capacity of the current connection, the number of packets being dispatched
+ * per second, etc. The throughput level events might not be consistent with the
+ * actual current throughput value being observed.
+ *
+ * @QCA_WLAN_THROUGHPUT_LEVEL_LOW: Low level of throughput
+ * @QCA_WLAN_THROUGHPUT_LEVEL_MEDIUM: Medium level of throughput
+ * @QCA_WLAN_THROUGHPUT_LEVEL_HIGH: High level of throughput
+ */
+enum qca_wlan_throughput_level {
+ QCA_WLAN_THROUGHPUT_LEVEL_LOW = 0,
+ QCA_WLAN_THROUGHPUT_LEVEL_MEDIUM = 1,
+ QCA_WLAN_THROUGHPUT_LEVEL_HIGH = 2,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_throughput_change - Vendor subcmd attributes to
+ * report throughput changes from the driver to user space. enum values are used
+ * for netlink attributes sent with
+ * %QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT sub command.
+ */
+enum qca_wlan_vendor_attr_throughput_change {
+ QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_INVALID = 0,
+ /* Indicates the direction of throughput in which the change is being
+ * reported. u8 attribute. Value is 0 for TX and 1 for RX.
+ */
+ QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_DIRECTION = 1,
+ /* Indicates the newly observed throughput level. enum
+ * qca_wlan_throughput_level describes the possible range of values.
+ * u8 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_THROUGHPUT_LEVEL = 2,
+ /* Indicates the driver's guidance on the new value to be set to
+ * kernel's TCP parameter tcp_limit_output_bytes. u32 attribute. The
+ * driver may optionally include this attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_TCP_LIMIT_OUTPUT_BYTES = 3,
+ /* Indicates the driver's guidance on the new value to be set to
+ * kernel's TCP parameter tcp_adv_win_scale. s8 attribute. Possible
+ * values are from -31 to 31. The driver may optionally include this
+ * attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_TCP_ADV_WIN_SCALE = 4,
+ /* Indicates the driver's guidance on the new value to be set to
+ * kernel's TCP parameter tcp_delack_seg. u32 attribute. The driver may
+ * optionally include this attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_TCP_DELACK_SEG = 5,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_MAX =
+ QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_coex_config_profiles - This enum defines different types of
+ * traffic streams that can be prioritized one over the other during coex
+ * scenarios.
+ * The types defined in this enum are categorized in the below manner.
+ * 0 - 31 values corresponds to WLAN
+ * 32 - 63 values corresponds to BT
+ * 64 - 95 values corresponds to Zigbee
+ * @QCA_WIFI_STA_DISCOVERY: Prioritize discovery frames for WLAN STA
+ * @QCA_WIFI_STA_CONNECTION: Prioritize connection frames for WLAN STA
+ * @QCA_WIFI_STA_CLASS_3_MGMT: Prioritize class 3 mgmt frames for WLAN STA
+ * @QCA_WIFI_STA_DATA : Prioritize data frames for WLAN STA
+ * @QCA_WIFI_STA_ALL: Priritize all frames for WLAN STA
+ * @QCA_WIFI_SAP_DISCOVERY: Prioritize discovery frames for WLAN SAP
+ * @QCA_WIFI_SAP_CONNECTION: Prioritize connection frames for WLAN SAP
+ * @QCA_WIFI_SAP_CLASS_3_MGMT: Prioritize class 3 mgmt frames for WLAN SAP
+ * @QCA_WIFI_SAP_DATA: Prioritize data frames for WLAN SAP
+ * @QCA_WIFI_SAP_ALL: Prioritize all frames for WLAN SAP
+ * @QCA_BT_A2DP: Prioritize BT A2DP
+ * @QCA_BT_BLE: Prioritize BT BLE
+ * @QCA_BT_SCO: Prioritize BT SCO
+ * @QCA_ZB_LOW: Prioritize Zigbee Low
+ * @QCA_ZB_HIGH: Prioritize Zigbee High
+ */
+enum qca_coex_config_profiles {
+ /* 0 - 31 corresponds to WLAN */
+ QCA_WIFI_STA_DISCOVERY = 0,
+ QCA_WIFI_STA_CONNECTION = 1,
+ QCA_WIFI_STA_CLASS_3_MGMT = 2,
+ QCA_WIFI_STA_DATA = 3,
+ QCA_WIFI_STA_ALL = 4,
+ QCA_WIFI_SAP_DISCOVERY = 5,
+ QCA_WIFI_SAP_CONNECTION = 6,
+ QCA_WIFI_SAP_CLASS_3_MGMT = 7,
+ QCA_WIFI_SAP_DATA = 8,
+ QCA_WIFI_SAP_ALL = 9,
+ QCA_WIFI_CASE_MAX = 31,
+ /* 32 - 63 corresponds to BT */
+ QCA_BT_A2DP = 32,
+ QCA_BT_BLE = 33,
+ QCA_BT_SCO = 34,
+ QCA_BT_CASE_MAX = 63,
+ /* 64 - 95 corresponds to Zigbee */
+ QCA_ZB_LOW = 64,
+ QCA_ZB_HIGH = 65,
+ QCA_ZB_CASE_MAX = 95,
+ /* 0xff is default value if the u8 profile value is not set. */
+ QCA_COEX_CONFIG_PROFILE_DEFAULT_VALUE = 255
+};
+
+/**
+ * enum qca_vendor_attr_coex_config_types - Coex configurations types.
+ * This enum defines the valid set of values of coex configuration types. These
+ * values may used by attribute
+ * %QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_CONFIG_TYPE.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_COEX_RESET: Reset all the
+ * weights to default values.
+ * @QCA_WLAN_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_COEX_START: Start to config
+ * weights with configurability value.
+ */
+enum qca_vendor_attr_coex_config_types {
+ QCA_WLAN_VENDOR_ATTR_COEX_CONFIG_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_COEX_RESET = 1,
+ QCA_WLAN_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_COEX_START = 2,
+};
+
+/**
+ * enum qca_vendor_attr_coex_config - Specifies vendor coex config attributes
+ *
+ * @QCA_VENDOR_ATTR_COEX_CONFIG_PROFILES: This attribute contains variable
+ * length array of 8-bit values from enum qca_coex_config_profiles.
+ * FW will prioritize the profiles in the order given in the array encapsulated
+ * in this attribute.
+ * For example:
+ * -----------------------------------------------------------------------
+ * | 1 | 34 | 32 | 65 |
+ * -----------------------------------------------------------------------
+ * If the attribute contains the values defined in above array then it means
+ * 1) Wifi STA connection has priority over BT_SCO, BT_A2DP and ZIGBEE HIGH.
+ * 2) BT_SCO has priority over BT_A2DP.
+ * 3) BT_A2DP has priority over ZIGBEE HIGH.
+ * Profiles which are not listed in this array shall not be preferred over the
+ * profiles which are listed in the array as a part of this attribute.
+ */
+enum qca_vendor_attr_coex_config {
+ QCA_VENDOR_ATTR_COEX_CONFIG_INVALID = 0,
+ QCA_VENDOR_ATTR_COEX_CONFIG_PROFILES = 1,
+
+ /* Keep last */
+ QCA_VENDOR_ATTR_COEX_CONFIG_AFTER_LAST,
+ QCA_VENDOR_ATTR_COEX_CONFIG_MAX =
+ QCA_VENDOR_ATTR_COEX_CONFIG_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_vendor_attr_coex_config_three_way - Specifies vendor coex config
+ * attributes
+ * Attributes for data used by QCA_NL80211_VENDOR_SUBCMD_COEX_CONFIG
+ *
+ * QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_CONFIG_TYPE: u32 attribute.
+ * Indicate config type.
+ * The config types are 32-bit values from qca_vendor_attr_coex_config_types
+ *
+ * @QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_1: u32 attribute.
+ * Indicate the Priority 1 profiles.
+ * The profiles are 8-bit values from enum qca_coex_config_profiles.
+ * In same priority level, maximum to 4 profiles can be set here.
+ * @QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_2: u32 attribute.
+ * Indicate the Priority 2 profiles.
+ * The profiles are 8-bit values from enum qca_coex_config_profiles.
+ * In same priority level, maximum to 4 profiles can be set here.
+ * @QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_3: u32 attribute.
+ * Indicate the Priority 3 profiles.
+ * The profiles are 8-bit values from enum qca_coex_config_profiles.
+ * In same priority level, maximum to 4 profiles can be set here.
+ * @QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_4: u32 attribute.
+ * Indicate the Priority 4 profiles.
+ * The profiles are 8-bit values from enum qca_coex_config_profiles.
+ * In same priority level, maximum to 4 profiles can be set here.
+ * NOTE:
+ * Limitations for QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_x priority
+ * arrangement:
+ * 1: In the same u32 attribute (priority x), the profiles enum values own
+ * same priority level.
+ * 2: 0xff is default value if the u8 profile value is not set.
+ * 3: max to 4 rules/profiles in same priority level.
+ * 4: max to 4 priority level (priority 1 - priority 4)
+ * 5: one priority level only supports one scenario from WLAN/BT/ZB,
+ * hybrid rules not support.
+ * 6: if WMI_COEX_CONFIG_THREE_WAY_COEX_RESET called, priority x will
+ * remain blank to reset all parameters.
+ * For example:
+ *
+ * If the attributes as follow:
+ * priority 1:
+ * ------------------------------------
+ * | 0xff | 0 | 1 | 2 |
+ * ------------------------------------
+ * priority 2:
+ * -------------------------------------
+ * | 0xff | 0xff | 0xff | 32 |
+ * -------------------------------------
+ * priority 3:
+ * -------------------------------------
+ * | 0xff | 0xff | 0xff | 65 |
+ * -------------------------------------
+ * then it means:
+ * 1: WIFI_STA_DISCOVERY, WIFI_STA_CLASS_3_MGMT and WIFI_STA_CONNECTION
+ * owns same priority level.
+ * 2: WIFI_STA_DISCOVERY, WIFI_STA_CLASS_3_MGMT and WIFI_STA_CONNECTION
+ * has priority over BT_A2DP and ZB_HIGH.
+ * 3: BT_A2DP has priority over ZB_HIGH.
+ */
+
+enum qca_vendor_attr_coex_config_three_way {
+ QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_INVALID = 0,
+ QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_CONFIG_TYPE = 1,
+ QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_1 = 2,
+ QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_2 = 3,
+ QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_3 = 4,
+ QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_4 = 5,
+
+ /* Keep last */
+ QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_AFTER_LAST,
+ QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_MAX =
+ QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_link_properties - Represent the link properties.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_MAC_ADDR: MAC address of the peer
+ * (STA/AP) for the connected link.
+ * @QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_STA_FLAGS: Attribute containing a
+ * &struct nl80211_sta_flag_update for the respective connected link. MAC
+ * address of the peer represented by
+ * QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_MAC_ADDR.
+ */
+enum qca_wlan_vendor_attr_link_properties {
+ QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_INVALID = 0,
+ /* 1 - 3 are reserved */
+ QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_MAC_ADDR = 4,
+ QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_STA_FLAGS = 5,
+
+ /* Keep last */
+ QCA_VENDOR_ATTR_LINK_PROPERTIES_AFTER_LAST,
+ QCA_VENDOR_ATTR_LINK_PROPERTIES_MAX =
+ QCA_VENDOR_ATTR_LINK_PROPERTIES_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_vendor_attr_peer_stats_cache_type - Represents peer stats cache type
+ * This enum defines the valid set of values of peer stats cache types. These
+ * values are used by attribute
+ * %QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_TYPE.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_PEER_TX_RATE_STATS: Represents peer TX rate statistics
+ * @QCA_WLAN_VENDOR_ATTR_PEER_RX_RATE_STATS: Represents peer RX rate statistics
+ * @QCA_WLAN_VENDOR_ATTR_PEER_TX_SOJOURN_STATS: Represents peer TX sojourn
+ * statistics
+ */
+enum qca_vendor_attr_peer_stats_cache_type {
+ QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_TYPE_INVALID = 0,
+
+ QCA_WLAN_VENDOR_ATTR_PEER_TX_RATE_STATS,
+ QCA_WLAN_VENDOR_ATTR_PEER_RX_RATE_STATS,
+ QCA_WLAN_VENDOR_ATTR_PEER_TX_SOJOURN_STATS,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_peer_stats_cache_params - This enum defines
+ * attributes required for QCA_NL80211_VENDOR_SUBCMD_PEER_STATS_CACHE_FLUSH
+ * Information in these attributes is used to flush peer rate statistics from
+ * the driver to user application.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_TYPE: Unsigned 32-bit attribute
+ * Indicate peer statistics cache type.
+ * The statistics types are 32-bit values from
+ * enum qca_vendor_attr_peer_stats_cache_type.
+ * @QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_PEER_MAC: Unsigned 8-bit array
+ * of size 6 octets, representing the peer MAC address.
+ * @QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_DATA: Opaque data attribute
+ * containing buffer of statistics to send to application layer entity.
+ * @QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_PEER_COOKIE: Unsigned 64-bit attribute
+ * representing a cookie for peer unique session.
+ */
+enum qca_wlan_vendor_attr_peer_stats_cache_params {
+ QCA_WLAN_VENDOR_ATTR_PEER_STATS_INVALID = 0,
+
+ QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_TYPE = 1,
+ QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_PEER_MAC = 2,
+ QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_DATA = 3,
+ QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_PEER_COOKIE = 4,
+
+ /* Keep last */
+ QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_LAST,
+ QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_MAX =
+ QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_LAST - 1
+};
+
+/**
+ * enum qca_mpta_helper_attr_zigbee_state - Current Zigbee state
+ * This enum defines all the possible states of Zigbee, which can be
+ * delivered in the QCA_MPTA_HELPER_VENDOR_ATTR_ZIGBEE_STATE attribute.
+ *
+ * @ZIGBEE_IDLE: Zigbee in idle state
+ * @ZIGBEE_FORM_NETWORK: Zigbee forming network
+ * @ZIGBEE_WAIT_JOIN: Zigbee waiting for joining network
+ * @ZIGBEE_JOIN: Zigbee joining network
+ * @ZIGBEE_NETWORK_UP: Zigbee network is up
+ * @ZIGBEE_HMI: Zigbee in HMI mode
+ */
+enum qca_mpta_helper_attr_zigbee_state {
+ ZIGBEE_IDLE = 0,
+ ZIGBEE_FORM_NETWORK = 1,
+ ZIGBEE_WAIT_JOIN = 2,
+ ZIGBEE_JOIN = 3,
+ ZIGBEE_NETWORK_UP = 4,
+ ZIGBEE_HMI = 5,
+};
+
+/*
+ * enum qca_mpta_helper_vendor_attr - Attributes used in vendor sub-command
+ * QCA_NL80211_VENDOR_SUBCMD_MPTA_HELPER_CONFIG.
+ */
+enum qca_mpta_helper_vendor_attr {
+ QCA_MPTA_HELPER_VENDOR_ATTR_INVALID = 0,
+ /* Optional attribute used to update Zigbee state.
+ * enum qca_mpta_helper_attr_zigbee_state.
+ * NLA_U32 attribute.
+ */
+ QCA_MPTA_HELPER_VENDOR_ATTR_ZIGBEE_STATE = 1,
+ /* Optional attribute used to configure WLAN duration for Shape-OCS
+ * during interrupt.
+ * Set in pair with QCA_MPTA_HELPER_VENDOR_ATTR_INT_NON_WLAN_DURATION.
+ * Value range 0 ~ 300 (ms).
+ * NLA_U32 attribute.
+ */
+ QCA_MPTA_HELPER_VENDOR_ATTR_INT_WLAN_DURATION = 2,
+ /* Optional attribute used to configure non-WLAN duration for Shape-OCS
+ * during interrupt.
+ * Set in pair with QCA_MPTA_HELPER_VENDOR_ATTR_INT_WLAN_DURATION.
+ * Value range 0 ~ 300 (ms).
+ * NLA_U32 attribute.
+ */
+ QCA_MPTA_HELPER_VENDOR_ATTR_INT_NON_WLAN_DURATION = 3,
+ /* Optional attribute used to configure WLAN duration for Shape-OCS
+ * monitor period.
+ * Set in pair with QCA_MPTA_HELPER_VENDOR_ATTR_MON_NON_WLAN_DURATION.
+ * Value range 0 ~ 300 (ms)
+ * NLA_U32 attribute
+ */
+ QCA_MPTA_HELPER_VENDOR_ATTR_MON_WLAN_DURATION = 4,
+ /* Optional attribute used to configure non-WLAN duration for Shape-OCS
+ * monitor period.
+ * Set in pair with QCA_MPTA_HELPER_VENDOR_ATTR_MON_WLAN_DURATION.
+ * Value range 0 ~ 300 (ms)
+ * NLA_U32 attribute
+ */
+ QCA_MPTA_HELPER_VENDOR_ATTR_MON_NON_WLAN_DURATION = 5,
+ /* Optional attribute used to configure OCS interrupt duration.
+ * Set in pair with QCA_MPTA_HELPER_VENDOR_ATTR_MON_OCS_DURATION.
+ * Value range 1000 ~ 20000 (ms)
+ * NLA_U32 attribute
+ */
+ QCA_MPTA_HELPER_VENDOR_ATTR_INT_OCS_DURATION = 6,
+ /* Optional attribute used to configure OCS monitor duration.
+ * Set in pair with QCA_MPTA_HELPER_VENDOR_ATTR_INT_OCS_DURATION.
+ * Value range 1000 ~ 20000 (ms)
+ * NLA_U32 attribute
+ */
+ QCA_MPTA_HELPER_VENDOR_ATTR_MON_OCS_DURATION = 7,
+ /* Optional attribute used to notify WLAN firmware the current Zigbee
+ * channel.
+ * Value range 11 ~ 26
+ * NLA_U32 attribute
+ */
+ QCA_MPTA_HELPER_VENDOR_ATTR_ZIGBEE_CHAN = 8,
+ /* Optional attribute used to configure WLAN mute duration.
+ * Value range 0 ~ 400 (ms)
+ * NLA_U32 attribute
+ */
+ QCA_MPTA_HELPER_VENDOR_ATTR_WLAN_MUTE_DURATION = 9,
+
+ /* keep last */
+ QCA_MPTA_HELPER_VENDOR_ATTR_AFTER_LAST,
+ QCA_MPTA_HELPER_VENDOR_ATTR_MAX =
+ QCA_MPTA_HELPER_VENDOR_ATTR_AFTER_LAST - 1
+};
+
#endif /* QCA_VENDOR_H */
diff --git a/freebsd/contrib/wpa/src/common/sae.h b/freebsd/contrib/wpa/src/common/sae.h
index a4270bc2..3eb6e323 100644
--- a/freebsd/contrib/wpa/src/common/sae.h
+++ b/freebsd/contrib/wpa/src/common/sae.h
@@ -39,16 +39,24 @@ struct sae_temporary_data {
struct crypto_bignum *prime_buf;
struct crypto_bignum *order_buf;
struct wpabuf *anti_clogging_token;
+ char *pw_id;
+ int vlan_id;
+ u8 bssid[ETH_ALEN];
+};
+
+enum sae_state {
+ SAE_NOTHING, SAE_COMMITTED, SAE_CONFIRMED, SAE_ACCEPTED
};
struct sae_data {
- enum { SAE_NOTHING, SAE_COMMITTED, SAE_CONFIRMED, SAE_ACCEPTED } state;
+ enum sae_state state;
u16 send_confirm;
u8 pmk[SAE_PMK_LEN];
u8 pmkid[SAE_PMKID_LEN];
struct crypto_bignum *peer_commit_scalar;
int group;
- int sync;
+ unsigned int sync; /* protocol instance variable: Sync */
+ u16 rc; /* protocol instance variable: Rc (received send-confirm) */
struct sae_temporary_data *tmp;
};
@@ -58,14 +66,15 @@ void sae_clear_data(struct sae_data *sae);
int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
const u8 *password, size_t password_len,
- struct sae_data *sae);
+ const char *identifier, struct sae_data *sae);
int sae_process_commit(struct sae_data *sae);
void sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
- const struct wpabuf *token);
+ const struct wpabuf *token, const char *identifier);
u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
const u8 **token, size_t *token_len, int *allowed_groups);
void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf);
int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len);
u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups, u16 group);
+const char * sae_state_txt(enum sae_state state);
#endif /* SAE_H */
diff --git a/freebsd/contrib/wpa/src/common/version.h b/freebsd/contrib/wpa/src/common/version.h
index 75e5c6e0..06fc5e4d 100644
--- a/freebsd/contrib/wpa/src/common/version.h
+++ b/freebsd/contrib/wpa/src/common/version.h
@@ -9,6 +9,6 @@
#define GIT_VERSION_STR_POSTFIX ""
#endif /* GIT_VERSION_STR_POSTFIX */
-#define VERSION_STR "2.6" VERSION_STR_POSTFIX GIT_VERSION_STR_POSTFIX
+#define VERSION_STR "2.8" VERSION_STR_POSTFIX GIT_VERSION_STR_POSTFIX
#endif /* VERSION_H */
diff --git a/freebsd/contrib/wpa/src/common/wpa_common.c b/freebsd/contrib/wpa/src/common/wpa_common.c
index f1802c36..b2b58793 100644
--- a/freebsd/contrib/wpa/src/common/wpa_common.c
+++ b/freebsd/contrib/wpa/src/common/wpa_common.c
@@ -2,7 +2,7 @@
/*
* WPA/RSN - Shared functions for supplicant and authenticator
- * Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2018, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -15,6 +15,7 @@
#include "crypto/sha1.h"
#include "crypto/sha256.h"
#include "crypto/sha384.h"
+#include "crypto/sha512.h"
#include "crypto/aes_wrap.h"
#include "crypto/crypto.h"
#include "ieee802_11_defs.h"
@@ -22,27 +23,151 @@
#include "wpa_common.h"
-static unsigned int wpa_kck_len(int akmp)
+static unsigned int wpa_kck_len(int akmp, size_t pmk_len)
{
- if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
+ switch (akmp) {
+ case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
+ case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
+ return 24;
+ case WPA_KEY_MGMT_FILS_SHA256:
+ case WPA_KEY_MGMT_FT_FILS_SHA256:
+ case WPA_KEY_MGMT_FILS_SHA384:
+ case WPA_KEY_MGMT_FT_FILS_SHA384:
+ return 0;
+ case WPA_KEY_MGMT_DPP:
+ return pmk_len / 2;
+ case WPA_KEY_MGMT_OWE:
+ return pmk_len / 2;
+ default:
+ return 16;
+ }
+}
+
+
+#ifdef CONFIG_IEEE80211R
+static unsigned int wpa_kck2_len(int akmp)
+{
+ switch (akmp) {
+ case WPA_KEY_MGMT_FT_FILS_SHA256:
+ return 16;
+ case WPA_KEY_MGMT_FT_FILS_SHA384:
return 24;
- return 16;
+ default:
+ return 0;
+ }
+}
+#endif /* CONFIG_IEEE80211R */
+
+
+static unsigned int wpa_kek_len(int akmp, size_t pmk_len)
+{
+ switch (akmp) {
+ case WPA_KEY_MGMT_FILS_SHA384:
+ case WPA_KEY_MGMT_FT_FILS_SHA384:
+ return 64;
+ case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
+ case WPA_KEY_MGMT_FILS_SHA256:
+ case WPA_KEY_MGMT_FT_FILS_SHA256:
+ case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
+ return 32;
+ case WPA_KEY_MGMT_DPP:
+ return pmk_len <= 32 ? 16 : 32;
+ case WPA_KEY_MGMT_OWE:
+ return pmk_len <= 32 ? 16 : 32;
+ default:
+ return 16;
+ }
}
-static unsigned int wpa_kek_len(int akmp)
+#ifdef CONFIG_IEEE80211R
+static unsigned int wpa_kek2_len(int akmp)
{
- if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
+ switch (akmp) {
+ case WPA_KEY_MGMT_FT_FILS_SHA256:
+ return 16;
+ case WPA_KEY_MGMT_FT_FILS_SHA384:
return 32;
- return 16;
+ default:
+ return 0;
+ }
}
+#endif /* CONFIG_IEEE80211R */
-unsigned int wpa_mic_len(int akmp)
+unsigned int wpa_mic_len(int akmp, size_t pmk_len)
{
- if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
+ switch (akmp) {
+ case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
+ case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
return 24;
- return 16;
+ case WPA_KEY_MGMT_FILS_SHA256:
+ case WPA_KEY_MGMT_FILS_SHA384:
+ case WPA_KEY_MGMT_FT_FILS_SHA256:
+ case WPA_KEY_MGMT_FT_FILS_SHA384:
+ return 0;
+ case WPA_KEY_MGMT_DPP:
+ return pmk_len / 2;
+ case WPA_KEY_MGMT_OWE:
+ return pmk_len / 2;
+ default:
+ return 16;
+ }
+}
+
+
+/**
+ * wpa_use_akm_defined - Is AKM-defined Key Descriptor Version used
+ * @akmp: WPA_KEY_MGMT_* used in key derivation
+ * Returns: 1 if AKM-defined Key Descriptor Version is used; 0 otherwise
+ */
+int wpa_use_akm_defined(int akmp)
+{
+ return akmp == WPA_KEY_MGMT_OSEN ||
+ akmp == WPA_KEY_MGMT_OWE ||
+ akmp == WPA_KEY_MGMT_DPP ||
+ akmp == WPA_KEY_MGMT_FT_IEEE8021X_SHA384 ||
+ wpa_key_mgmt_sae(akmp) ||
+ wpa_key_mgmt_suite_b(akmp) ||
+ wpa_key_mgmt_fils(akmp);
+}
+
+
+/**
+ * wpa_use_cmac - Is CMAC integrity algorithm used for EAPOL-Key MIC
+ * @akmp: WPA_KEY_MGMT_* used in key derivation
+ * Returns: 1 if CMAC is used; 0 otherwise
+ */
+int wpa_use_cmac(int akmp)
+{
+ return akmp == WPA_KEY_MGMT_OSEN ||
+ akmp == WPA_KEY_MGMT_OWE ||
+ akmp == WPA_KEY_MGMT_DPP ||
+ wpa_key_mgmt_ft(akmp) ||
+ wpa_key_mgmt_sha256(akmp) ||
+ wpa_key_mgmt_sae(akmp) ||
+ wpa_key_mgmt_suite_b(akmp);
+}
+
+
+/**
+ * wpa_use_aes_key_wrap - Is AES Keywrap algorithm used for EAPOL-Key Key Data
+ * @akmp: WPA_KEY_MGMT_* used in key derivation
+ * Returns: 1 if AES Keywrap is used; 0 otherwise
+ *
+ * Note: AKM 00-0F-AC:1 and 00-0F-AC:2 have special rules for selecting whether
+ * to use AES Keywrap based on the negotiated pairwise cipher. This function
+ * does not cover those special cases.
+ */
+int wpa_use_aes_key_wrap(int akmp)
+{
+ return akmp == WPA_KEY_MGMT_OSEN ||
+ akmp == WPA_KEY_MGMT_OWE ||
+ akmp == WPA_KEY_MGMT_DPP ||
+ wpa_key_mgmt_ft(akmp) ||
+ wpa_key_mgmt_sha256(akmp) ||
+ wpa_key_mgmt_sae(akmp) ||
+ wpa_key_mgmt_suite_b(akmp);
}
@@ -69,30 +194,50 @@ unsigned int wpa_mic_len(int akmp)
int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver,
const u8 *buf, size_t len, u8 *mic)
{
- u8 hash[SHA384_MAC_LEN];
+ u8 hash[SHA512_MAC_LEN];
+
+ if (key_len == 0) {
+ wpa_printf(MSG_DEBUG,
+ "WPA: KCK not set - cannot calculate MIC");
+ return -1;
+ }
switch (ver) {
#ifndef CONFIG_FIPS
case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4:
+ wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key MIC using HMAC-MD5");
return hmac_md5(key, key_len, buf, len, mic);
#endif /* CONFIG_FIPS */
case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES:
+ wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key MIC using HMAC-SHA1");
if (hmac_sha1(key, key_len, buf, len, hash))
return -1;
os_memcpy(mic, hash, MD5_MAC_LEN);
break;
#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W)
case WPA_KEY_INFO_TYPE_AES_128_CMAC:
+ wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key MIC using AES-CMAC");
return omac1_aes_128(key, buf, len, mic);
#endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */
case WPA_KEY_INFO_TYPE_AKM_DEFINED:
switch (akmp) {
+#ifdef CONFIG_SAE
+ case WPA_KEY_MGMT_SAE:
+ case WPA_KEY_MGMT_FT_SAE:
+ wpa_printf(MSG_DEBUG,
+ "WPA: EAPOL-Key MIC using AES-CMAC (AKM-defined - SAE)");
+ return omac1_aes_128(key, buf, len, mic);
+#endif /* CONFIG_SAE */
#ifdef CONFIG_HS20
case WPA_KEY_MGMT_OSEN:
+ wpa_printf(MSG_DEBUG,
+ "WPA: EAPOL-Key MIC using AES-CMAC (AKM-defined - OSEN)");
return omac1_aes_128(key, buf, len, mic);
#endif /* CONFIG_HS20 */
#ifdef CONFIG_SUITEB
case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
+ wpa_printf(MSG_DEBUG,
+ "WPA: EAPOL-Key MIC using HMAC-SHA256 (AKM-defined - Suite B)");
if (hmac_sha256(key, key_len, buf, len, hash))
return -1;
os_memcpy(mic, hash, MD5_MAC_LEN);
@@ -100,16 +245,79 @@ int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver,
#endif /* CONFIG_SUITEB */
#ifdef CONFIG_SUITEB192
case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
+ wpa_printf(MSG_DEBUG,
+ "WPA: EAPOL-Key MIC using HMAC-SHA384 (AKM-defined - Suite B 192-bit)");
if (hmac_sha384(key, key_len, buf, len, hash))
return -1;
os_memcpy(mic, hash, 24);
break;
#endif /* CONFIG_SUITEB192 */
+#ifdef CONFIG_OWE
+ case WPA_KEY_MGMT_OWE:
+ wpa_printf(MSG_DEBUG,
+ "WPA: EAPOL-Key MIC using HMAC-SHA%u (AKM-defined - OWE)",
+ (unsigned int) key_len * 8 * 2);
+ if (key_len == 128 / 8) {
+ if (hmac_sha256(key, key_len, buf, len, hash))
+ return -1;
+ } else if (key_len == 192 / 8) {
+ if (hmac_sha384(key, key_len, buf, len, hash))
+ return -1;
+ } else if (key_len == 256 / 8) {
+ if (hmac_sha512(key, key_len, buf, len, hash))
+ return -1;
+ } else {
+ wpa_printf(MSG_INFO,
+ "OWE: Unsupported KCK length: %u",
+ (unsigned int) key_len);
+ return -1;
+ }
+ os_memcpy(mic, hash, key_len);
+ break;
+#endif /* CONFIG_OWE */
+#ifdef CONFIG_DPP
+ case WPA_KEY_MGMT_DPP:
+ wpa_printf(MSG_DEBUG,
+ "WPA: EAPOL-Key MIC using HMAC-SHA%u (AKM-defined - DPP)",
+ (unsigned int) key_len * 8 * 2);
+ if (key_len == 128 / 8) {
+ if (hmac_sha256(key, key_len, buf, len, hash))
+ return -1;
+ } else if (key_len == 192 / 8) {
+ if (hmac_sha384(key, key_len, buf, len, hash))
+ return -1;
+ } else if (key_len == 256 / 8) {
+ if (hmac_sha512(key, key_len, buf, len, hash))
+ return -1;
+ } else {
+ wpa_printf(MSG_INFO,
+ "DPP: Unsupported KCK length: %u",
+ (unsigned int) key_len);
+ return -1;
+ }
+ os_memcpy(mic, hash, key_len);
+ break;
+#endif /* CONFIG_DPP */
+#if defined(CONFIG_IEEE80211R) && defined(CONFIG_SHA384)
+ case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
+ wpa_printf(MSG_DEBUG,
+ "WPA: EAPOL-Key MIC using HMAC-SHA384 (AKM-defined - FT 802.1X SHA384)");
+ if (hmac_sha384(key, key_len, buf, len, hash))
+ return -1;
+ os_memcpy(mic, hash, 24);
+ break;
+#endif /* CONFIG_IEEE80211R && CONFIG_SHA384 */
default:
+ wpa_printf(MSG_DEBUG,
+ "WPA: EAPOL-Key MIC algorithm not known (AKM-defined - akmp=0x%x)",
+ akmp);
return -1;
}
break;
default:
+ wpa_printf(MSG_DEBUG,
+ "WPA: EAPOL-Key MIC algorithm not known (ver=%d)",
+ ver);
return -1;
}
@@ -134,21 +342,32 @@ int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver,
* IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
* PTK = PRF-X(PMK, "Pairwise key expansion",
* Min(AA, SA) || Max(AA, SA) ||
- * Min(ANonce, SNonce) || Max(ANonce, SNonce))
+ * Min(ANonce, SNonce) || Max(ANonce, SNonce)
+ * [ || Z.x ])
*
- * STK = PRF-X(SMK, "Peer key expansion",
- * Min(MAC_I, MAC_P) || Max(MAC_I, MAC_P) ||
- * Min(INonce, PNonce) || Max(INonce, PNonce))
+ * The optional Z.x component is used only with DPP and that part is not defined
+ * in IEEE 802.11.
*/
int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label,
const u8 *addr1, const u8 *addr2,
const u8 *nonce1, const u8 *nonce2,
- struct wpa_ptk *ptk, int akmp, int cipher)
+ struct wpa_ptk *ptk, int akmp, int cipher,
+ const u8 *z, size_t z_len)
{
- u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN];
+#define MAX_Z_LEN 66 /* with NIST P-521 */
+ u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN + MAX_Z_LEN];
+ size_t data_len = 2 * ETH_ALEN + 2 * WPA_NONCE_LEN;
u8 tmp[WPA_KCK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN];
size_t ptk_len;
+ if (pmk_len == 0) {
+ wpa_printf(MSG_ERROR, "WPA: No PMK set for PTK derivation");
+ return -1;
+ }
+
+ if (z_len > MAX_Z_LEN)
+ return -1;
+
if (os_memcmp(addr1, addr2, ETH_ALEN) < 0) {
os_memcpy(data, addr1, ETH_ALEN);
os_memcpy(data + ETH_ALEN, addr2, ETH_ALEN);
@@ -167,29 +386,74 @@ int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label,
WPA_NONCE_LEN);
}
- ptk->kck_len = wpa_kck_len(akmp);
- ptk->kek_len = wpa_kek_len(akmp);
+ if (z && z_len) {
+ os_memcpy(data + 2 * ETH_ALEN + 2 * WPA_NONCE_LEN, z, z_len);
+ data_len += z_len;
+ }
+
+ ptk->kck_len = wpa_kck_len(akmp, pmk_len);
+ ptk->kek_len = wpa_kek_len(akmp, pmk_len);
ptk->tk_len = wpa_cipher_key_len(cipher);
+ if (ptk->tk_len == 0) {
+ wpa_printf(MSG_ERROR,
+ "WPA: Unsupported cipher (0x%x) used in PTK derivation",
+ cipher);
+ return -1;
+ }
ptk_len = ptk->kck_len + ptk->kek_len + ptk->tk_len;
-#ifdef CONFIG_SUITEB192
- if (wpa_key_mgmt_sha384(akmp))
- sha384_prf(pmk, pmk_len, label, data, sizeof(data),
- tmp, ptk_len);
- else
-#endif /* CONFIG_SUITEB192 */
-#ifdef CONFIG_IEEE80211W
- if (wpa_key_mgmt_sha256(akmp))
- sha256_prf(pmk, pmk_len, label, data, sizeof(data),
- tmp, ptk_len);
- else
-#endif /* CONFIG_IEEE80211W */
- sha1_prf(pmk, pmk_len, label, data, sizeof(data), tmp, ptk_len);
+ if (wpa_key_mgmt_sha384(akmp)) {
+#if defined(CONFIG_SUITEB192) || defined(CONFIG_FILS)
+ wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA384)");
+ if (sha384_prf(pmk, pmk_len, label, data, data_len,
+ tmp, ptk_len) < 0)
+ return -1;
+#else /* CONFIG_SUITEB192 || CONFIG_FILS */
+ return -1;
+#endif /* CONFIG_SUITEB192 || CONFIG_FILS */
+ } else if (wpa_key_mgmt_sha256(akmp) || akmp == WPA_KEY_MGMT_OWE) {
+#if defined(CONFIG_IEEE80211W) || defined(CONFIG_SAE) || defined(CONFIG_FILS)
+ wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA256)");
+ if (sha256_prf(pmk, pmk_len, label, data, data_len,
+ tmp, ptk_len) < 0)
+ return -1;
+#else /* CONFIG_IEEE80211W or CONFIG_SAE or CONFIG_FILS */
+ return -1;
+#endif /* CONFIG_IEEE80211W or CONFIG_SAE or CONFIG_FILS */
+#ifdef CONFIG_DPP
+ } else if (akmp == WPA_KEY_MGMT_DPP && pmk_len == 32) {
+ wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA256)");
+ if (sha256_prf(pmk, pmk_len, label, data, data_len,
+ tmp, ptk_len) < 0)
+ return -1;
+ } else if (akmp == WPA_KEY_MGMT_DPP && pmk_len == 48) {
+ wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA384)");
+ if (sha384_prf(pmk, pmk_len, label, data, data_len,
+ tmp, ptk_len) < 0)
+ return -1;
+ } else if (akmp == WPA_KEY_MGMT_DPP && pmk_len == 64) {
+ wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA512)");
+ if (sha512_prf(pmk, pmk_len, label, data, data_len,
+ tmp, ptk_len) < 0)
+ return -1;
+ } else if (akmp == WPA_KEY_MGMT_DPP) {
+ wpa_printf(MSG_INFO, "DPP: Unknown PMK length %u",
+ (unsigned int) pmk_len);
+ return -1;
+#endif /* CONFIG_DPP */
+ } else {
+ wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA1)");
+ if (sha1_prf(pmk, pmk_len, label, data, data_len, tmp,
+ ptk_len) < 0)
+ return -1;
+ }
wpa_printf(MSG_DEBUG, "WPA: PTK derivation - A1=" MACSTR " A2=" MACSTR,
MAC2STR(addr1), MAC2STR(addr2));
wpa_hexdump(MSG_DEBUG, "WPA: Nonce1", nonce1, WPA_NONCE_LEN);
wpa_hexdump(MSG_DEBUG, "WPA: Nonce2", nonce2, WPA_NONCE_LEN);
+ if (z && z_len)
+ wpa_hexdump_key(MSG_DEBUG, "WPA: Z.x", z, z_len);
wpa_hexdump_key(MSG_DEBUG, "WPA: PMK", pmk, pmk_len);
wpa_hexdump_key(MSG_DEBUG, "WPA: PTK", tmp, ptk_len);
@@ -202,11 +466,292 @@ int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label,
os_memcpy(ptk->tk, tmp + ptk->kck_len + ptk->kek_len, ptk->tk_len);
wpa_hexdump_key(MSG_DEBUG, "WPA: TK", ptk->tk, ptk->tk_len);
+ ptk->kek2_len = 0;
+ ptk->kck2_len = 0;
+
os_memset(tmp, 0, sizeof(tmp));
+ os_memset(data, 0, data_len);
+ return 0;
+}
+
+#ifdef CONFIG_FILS
+
+int fils_rmsk_to_pmk(int akmp, const u8 *rmsk, size_t rmsk_len,
+ const u8 *snonce, const u8 *anonce, const u8 *dh_ss,
+ size_t dh_ss_len, u8 *pmk, size_t *pmk_len)
+{
+ u8 nonces[2 * FILS_NONCE_LEN];
+ const u8 *addr[2];
+ size_t len[2];
+ size_t num_elem;
+ int res;
+
+ /* PMK = HMAC-Hash(SNonce || ANonce, rMSK [ || DHss ]) */
+ wpa_printf(MSG_DEBUG, "FILS: rMSK to PMK derivation");
+
+ if (wpa_key_mgmt_sha384(akmp))
+ *pmk_len = SHA384_MAC_LEN;
+ else if (wpa_key_mgmt_sha256(akmp))
+ *pmk_len = SHA256_MAC_LEN;
+ else
+ return -1;
+
+ wpa_hexdump_key(MSG_DEBUG, "FILS: rMSK", rmsk, rmsk_len);
+ wpa_hexdump(MSG_DEBUG, "FILS: SNonce", snonce, FILS_NONCE_LEN);
+ wpa_hexdump(MSG_DEBUG, "FILS: ANonce", anonce, FILS_NONCE_LEN);
+ wpa_hexdump(MSG_DEBUG, "FILS: DHss", dh_ss, dh_ss_len);
+
+ os_memcpy(nonces, snonce, FILS_NONCE_LEN);
+ os_memcpy(&nonces[FILS_NONCE_LEN], anonce, FILS_NONCE_LEN);
+ addr[0] = rmsk;
+ len[0] = rmsk_len;
+ num_elem = 1;
+ if (dh_ss) {
+ addr[1] = dh_ss;
+ len[1] = dh_ss_len;
+ num_elem++;
+ }
+ if (wpa_key_mgmt_sha384(akmp))
+ res = hmac_sha384_vector(nonces, 2 * FILS_NONCE_LEN, num_elem,
+ addr, len, pmk);
+ else
+ res = hmac_sha256_vector(nonces, 2 * FILS_NONCE_LEN, num_elem,
+ addr, len, pmk);
+ if (res == 0)
+ wpa_hexdump_key(MSG_DEBUG, "FILS: PMK", pmk, *pmk_len);
+ else
+ *pmk_len = 0;
+ return res;
+}
+
+
+int fils_pmkid_erp(int akmp, const u8 *reauth, size_t reauth_len,
+ u8 *pmkid)
+{
+ const u8 *addr[1];
+ size_t len[1];
+ u8 hash[SHA384_MAC_LEN];
+ int res;
+
+ /* PMKID = Truncate-128(Hash(EAP-Initiate/Reauth)) */
+ addr[0] = reauth;
+ len[0] = reauth_len;
+ if (wpa_key_mgmt_sha384(akmp))
+ res = sha384_vector(1, addr, len, hash);
+ else if (wpa_key_mgmt_sha256(akmp))
+ res = sha256_vector(1, addr, len, hash);
+ else
+ return -1;
+ if (res)
+ return res;
+ os_memcpy(pmkid, hash, PMKID_LEN);
+ wpa_hexdump(MSG_DEBUG, "FILS: PMKID", pmkid, PMKID_LEN);
return 0;
}
+int fils_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const u8 *spa, const u8 *aa,
+ const u8 *snonce, const u8 *anonce, const u8 *dhss,
+ size_t dhss_len, struct wpa_ptk *ptk,
+ u8 *ick, size_t *ick_len, int akmp, int cipher,
+ u8 *fils_ft, size_t *fils_ft_len)
+{
+ u8 *data, *pos;
+ size_t data_len;
+ u8 tmp[FILS_ICK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN +
+ FILS_FT_MAX_LEN];
+ size_t key_data_len;
+ const char *label = "FILS PTK Derivation";
+ int ret = -1;
+
+ /*
+ * FILS-Key-Data = PRF-X(PMK, "FILS PTK Derivation",
+ * SPA || AA || SNonce || ANonce [ || DHss ])
+ * ICK = L(FILS-Key-Data, 0, ICK_bits)
+ * KEK = L(FILS-Key-Data, ICK_bits, KEK_bits)
+ * TK = L(FILS-Key-Data, ICK_bits + KEK_bits, TK_bits)
+ * If doing FT initial mobility domain association:
+ * FILS-FT = L(FILS-Key-Data, ICK_bits + KEK_bits + TK_bits,
+ * FILS-FT_bits)
+ */
+ data_len = 2 * ETH_ALEN + 2 * FILS_NONCE_LEN + dhss_len;
+ data = os_malloc(data_len);
+ if (!data)
+ goto err;
+ pos = data;
+ os_memcpy(pos, spa, ETH_ALEN);
+ pos += ETH_ALEN;
+ os_memcpy(pos, aa, ETH_ALEN);
+ pos += ETH_ALEN;
+ os_memcpy(pos, snonce, FILS_NONCE_LEN);
+ pos += FILS_NONCE_LEN;
+ os_memcpy(pos, anonce, FILS_NONCE_LEN);
+ pos += FILS_NONCE_LEN;
+ if (dhss)
+ os_memcpy(pos, dhss, dhss_len);
+
+ ptk->kck_len = 0;
+ ptk->kek_len = wpa_kek_len(akmp, pmk_len);
+ ptk->tk_len = wpa_cipher_key_len(cipher);
+ if (wpa_key_mgmt_sha384(akmp))
+ *ick_len = 48;
+ else if (wpa_key_mgmt_sha256(akmp))
+ *ick_len = 32;
+ else
+ goto err;
+ key_data_len = *ick_len + ptk->kek_len + ptk->tk_len;
+
+ if (fils_ft && fils_ft_len) {
+ if (akmp == WPA_KEY_MGMT_FT_FILS_SHA256) {
+ *fils_ft_len = 32;
+ } else if (akmp == WPA_KEY_MGMT_FT_FILS_SHA384) {
+ *fils_ft_len = 48;
+ } else {
+ *fils_ft_len = 0;
+ fils_ft = NULL;
+ }
+ key_data_len += *fils_ft_len;
+ }
+
+ if (wpa_key_mgmt_sha384(akmp)) {
+ wpa_printf(MSG_DEBUG, "FILS: PTK derivation using PRF(SHA384)");
+ if (sha384_prf(pmk, pmk_len, label, data, data_len,
+ tmp, key_data_len) < 0)
+ goto err;
+ } else {
+ wpa_printf(MSG_DEBUG, "FILS: PTK derivation using PRF(SHA256)");
+ if (sha256_prf(pmk, pmk_len, label, data, data_len,
+ tmp, key_data_len) < 0)
+ goto err;
+ }
+
+ wpa_printf(MSG_DEBUG, "FILS: PTK derivation - SPA=" MACSTR
+ " AA=" MACSTR, MAC2STR(spa), MAC2STR(aa));
+ wpa_hexdump(MSG_DEBUG, "FILS: SNonce", snonce, FILS_NONCE_LEN);
+ wpa_hexdump(MSG_DEBUG, "FILS: ANonce", anonce, FILS_NONCE_LEN);
+ if (dhss)
+ wpa_hexdump_key(MSG_DEBUG, "FILS: DHss", dhss, dhss_len);
+ wpa_hexdump_key(MSG_DEBUG, "FILS: PMK", pmk, pmk_len);
+ wpa_hexdump_key(MSG_DEBUG, "FILS: FILS-Key-Data", tmp, key_data_len);
+
+ os_memcpy(ick, tmp, *ick_len);
+ wpa_hexdump_key(MSG_DEBUG, "FILS: ICK", ick, *ick_len);
+
+ os_memcpy(ptk->kek, tmp + *ick_len, ptk->kek_len);
+ wpa_hexdump_key(MSG_DEBUG, "FILS: KEK", ptk->kek, ptk->kek_len);
+
+ os_memcpy(ptk->tk, tmp + *ick_len + ptk->kek_len, ptk->tk_len);
+ wpa_hexdump_key(MSG_DEBUG, "FILS: TK", ptk->tk, ptk->tk_len);
+
+ if (fils_ft && fils_ft_len) {
+ os_memcpy(fils_ft, tmp + *ick_len + ptk->kek_len + ptk->tk_len,
+ *fils_ft_len);
+ wpa_hexdump_key(MSG_DEBUG, "FILS: FILS-FT",
+ fils_ft, *fils_ft_len);
+ }
+
+ ptk->kek2_len = 0;
+ ptk->kck2_len = 0;
+
+ os_memset(tmp, 0, sizeof(tmp));
+ ret = 0;
+err:
+ bin_clear_free(data, data_len);
+ return ret;
+}
+
+
+int fils_key_auth_sk(const u8 *ick, size_t ick_len, const u8 *snonce,
+ const u8 *anonce, const u8 *sta_addr, const u8 *bssid,
+ const u8 *g_sta, size_t g_sta_len,
+ const u8 *g_ap, size_t g_ap_len,
+ int akmp, u8 *key_auth_sta, u8 *key_auth_ap,
+ size_t *key_auth_len)
+{
+ const u8 *addr[6];
+ size_t len[6];
+ size_t num_elem = 4;
+ int res;
+
+ wpa_printf(MSG_DEBUG, "FILS: Key-Auth derivation: STA-MAC=" MACSTR
+ " AP-BSSID=" MACSTR, MAC2STR(sta_addr), MAC2STR(bssid));
+ wpa_hexdump_key(MSG_DEBUG, "FILS: ICK", ick, ick_len);
+ wpa_hexdump(MSG_DEBUG, "FILS: SNonce", snonce, FILS_NONCE_LEN);
+ wpa_hexdump(MSG_DEBUG, "FILS: ANonce", anonce, FILS_NONCE_LEN);
+ wpa_hexdump(MSG_DEBUG, "FILS: gSTA", g_sta, g_sta_len);
+ wpa_hexdump(MSG_DEBUG, "FILS: gAP", g_ap, g_ap_len);
+
+ /*
+ * For (Re)Association Request frame (STA->AP):
+ * Key-Auth = HMAC-Hash(ICK, SNonce || ANonce || STA-MAC || AP-BSSID
+ * [ || gSTA || gAP ])
+ */
+ addr[0] = snonce;
+ len[0] = FILS_NONCE_LEN;
+ addr[1] = anonce;
+ len[1] = FILS_NONCE_LEN;
+ addr[2] = sta_addr;
+ len[2] = ETH_ALEN;
+ addr[3] = bssid;
+ len[3] = ETH_ALEN;
+ if (g_sta && g_ap_len && g_ap && g_ap_len) {
+ addr[4] = g_sta;
+ len[4] = g_sta_len;
+ addr[5] = g_ap;
+ len[5] = g_ap_len;
+ num_elem = 6;
+ }
+
+ if (wpa_key_mgmt_sha384(akmp)) {
+ *key_auth_len = 48;
+ res = hmac_sha384_vector(ick, ick_len, num_elem, addr, len,
+ key_auth_sta);
+ } else if (wpa_key_mgmt_sha256(akmp)) {
+ *key_auth_len = 32;
+ res = hmac_sha256_vector(ick, ick_len, num_elem, addr, len,
+ key_auth_sta);
+ } else {
+ return -1;
+ }
+ if (res < 0)
+ return res;
+
+ /*
+ * For (Re)Association Response frame (AP->STA):
+ * Key-Auth = HMAC-Hash(ICK, ANonce || SNonce || AP-BSSID || STA-MAC
+ * [ || gAP || gSTA ])
+ */
+ addr[0] = anonce;
+ addr[1] = snonce;
+ addr[2] = bssid;
+ addr[3] = sta_addr;
+ if (g_sta && g_ap_len && g_ap && g_ap_len) {
+ addr[4] = g_ap;
+ len[4] = g_ap_len;
+ addr[5] = g_sta;
+ len[5] = g_sta_len;
+ }
+
+ if (wpa_key_mgmt_sha384(akmp))
+ res = hmac_sha384_vector(ick, ick_len, num_elem, addr, len,
+ key_auth_ap);
+ else if (wpa_key_mgmt_sha256(akmp))
+ res = hmac_sha256_vector(ick, ick_len, num_elem, addr, len,
+ key_auth_ap);
+ if (res < 0)
+ return res;
+
+ wpa_hexdump(MSG_DEBUG, "FILS: Key-Auth (STA)",
+ key_auth_sta, *key_auth_len);
+ wpa_hexdump(MSG_DEBUG, "FILS: Key-Auth (AP)",
+ key_auth_ap, *key_auth_len);
+
+ return 0;
+}
+
+#endif /* CONFIG_FILS */
+
+
#ifdef CONFIG_IEEE80211R
int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr,
const u8 *ap_addr, u8 transaction_seqnum,
@@ -218,14 +763,23 @@ int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr,
const u8 *addr[9];
size_t len[9];
size_t i, num_elem = 0;
- u8 zero_mic[16];
-
- if (kck_len != 16) {
+ u8 zero_mic[24];
+ size_t mic_len, fte_fixed_len;
+
+ if (kck_len == 16) {
+ mic_len = 16;
+#ifdef CONFIG_SHA384
+ } else if (kck_len == 24) {
+ mic_len = 24;
+#endif /* CONFIG_SHA384 */
+ } else {
wpa_printf(MSG_WARNING, "FT: Unsupported KCK length %u",
(unsigned int) kck_len);
return -1;
}
+ fte_fixed_len = sizeof(struct rsn_ftie) - 16 + mic_len;
+
addr[num_elem] = sta_addr;
len[num_elem] = ETH_ALEN;
num_elem++;
@@ -249,7 +803,7 @@ int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr,
num_elem++;
}
if (ftie) {
- if (ftie_len < 2 + sizeof(struct rsn_ftie))
+ if (ftie_len < 2 + fte_fixed_len)
return -1;
/* IE hdr and mic_control */
@@ -258,14 +812,14 @@ int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr,
num_elem++;
/* MIC field with all zeros */
- os_memset(zero_mic, 0, sizeof(zero_mic));
+ os_memset(zero_mic, 0, mic_len);
addr[num_elem] = zero_mic;
- len[num_elem] = sizeof(zero_mic);
+ len[num_elem] = mic_len;
num_elem++;
/* Rest of FTIE */
- addr[num_elem] = ftie + 2 + 2 + 16;
- len[num_elem] = ftie_len - (2 + 2 + 16);
+ addr[num_elem] = ftie + 2 + 2 + mic_len;
+ len[num_elem] = ftie_len - (2 + 2 + mic_len);
num_elem++;
}
if (ric) {
@@ -276,7 +830,17 @@ int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr,
for (i = 0; i < num_elem; i++)
wpa_hexdump(MSG_MSGDUMP, "FT: MIC data", addr[i], len[i]);
- if (omac1_aes_128_vector(kck, num_elem, addr, len, mic))
+#ifdef CONFIG_SHA384
+ if (kck_len == 24) {
+ u8 hash[SHA384_MAC_LEN];
+
+ if (hmac_sha384_vector(kck, kck_len, num_elem, addr, len, hash))
+ return -1;
+ os_memcpy(mic, hash, 24);
+ }
+#endif /* CONFIG_SHA384 */
+ if (kck_len == 16 &&
+ omac1_aes_128_vector(kck, num_elem, addr, len, mic))
return -1;
return 0;
@@ -284,23 +848,27 @@ int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr,
static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
- struct wpa_ft_ies *parse)
+ struct wpa_ft_ies *parse, int use_sha384)
{
const u8 *end, *pos;
parse->ftie = ie;
parse->ftie_len = ie_len;
- pos = ie + sizeof(struct rsn_ftie);
+ pos = ie + (use_sha384 ? sizeof(struct rsn_ftie_sha384) :
+ sizeof(struct rsn_ftie));
end = ie + ie_len;
+ wpa_hexdump(MSG_DEBUG, "FT: Parse FTE subelements", pos, end - pos);
while (end - pos >= 2) {
u8 id, len;
id = *pos++;
len = *pos++;
- if (len > end - pos)
+ if (len > end - pos) {
+ wpa_printf(MSG_DEBUG, "FT: Truncated subelement");
break;
+ }
switch (id) {
case FTIE_SUBELEM_R1KH_ID:
@@ -332,6 +900,15 @@ static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
parse->igtk_len = len;
break;
#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_OCV
+ case FTIE_SUBELEM_OCI:
+ parse->oci = pos;
+ parse->oci_len = len;
+ break;
+#endif /* CONFIG_OCV */
+ default:
+ wpa_printf(MSG_DEBUG, "FT: Unknown subelem id %u", id);
+ break;
}
pos += len;
@@ -342,13 +919,19 @@ static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
- struct wpa_ft_ies *parse)
+ struct wpa_ft_ies *parse, int use_sha384)
{
const u8 *end, *pos;
struct wpa_ie_data data;
int ret;
const struct rsn_ftie *ftie;
int prot_ie_count = 0;
+ int update_use_sha384 = 0;
+
+ if (use_sha384 < 0) {
+ use_sha384 = 0;
+ update_use_sha384 = 1;
+ }
os_memset(parse, 0, sizeof(*parse));
if (ies == NULL)
@@ -366,6 +949,7 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
switch (id) {
case WLAN_EID_RSN:
+ wpa_hexdump(MSG_DEBUG, "FT: RSNE", pos, len);
parse->rsn = pos;
parse->rsn_len = len;
ret = wpa_parse_wpa_ie_rsn(parse->rsn - 2,
@@ -378,22 +962,65 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
}
if (data.num_pmkid == 1 && data.pmkid)
parse->rsn_pmkid = data.pmkid;
+ parse->key_mgmt = data.key_mgmt;
+ parse->pairwise_cipher = data.pairwise_cipher;
+ if (update_use_sha384) {
+ use_sha384 =
+ wpa_key_mgmt_sha384(parse->key_mgmt);
+ update_use_sha384 = 0;
+ }
break;
case WLAN_EID_MOBILITY_DOMAIN:
+ wpa_hexdump(MSG_DEBUG, "FT: MDE", pos, len);
if (len < sizeof(struct rsn_mdie))
return -1;
parse->mdie = pos;
parse->mdie_len = len;
break;
case WLAN_EID_FAST_BSS_TRANSITION:
+ wpa_hexdump(MSG_DEBUG, "FT: FTE", pos, len);
+ if (use_sha384) {
+ const struct rsn_ftie_sha384 *ftie_sha384;
+
+ if (len < sizeof(*ftie_sha384))
+ return -1;
+ ftie_sha384 =
+ (const struct rsn_ftie_sha384 *) pos;
+ wpa_hexdump(MSG_DEBUG, "FT: FTE-MIC Control",
+ ftie_sha384->mic_control, 2);
+ wpa_hexdump(MSG_DEBUG, "FT: FTE-MIC",
+ ftie_sha384->mic,
+ sizeof(ftie_sha384->mic));
+ wpa_hexdump(MSG_DEBUG, "FT: FTE-ANonce",
+ ftie_sha384->anonce,
+ WPA_NONCE_LEN);
+ wpa_hexdump(MSG_DEBUG, "FT: FTE-SNonce",
+ ftie_sha384->snonce,
+ WPA_NONCE_LEN);
+ prot_ie_count = ftie_sha384->mic_control[1];
+ if (wpa_ft_parse_ftie(pos, len, parse, 1) < 0)
+ return -1;
+ break;
+ }
+
if (len < sizeof(*ftie))
return -1;
ftie = (const struct rsn_ftie *) pos;
+ wpa_hexdump(MSG_DEBUG, "FT: FTE-MIC Control",
+ ftie->mic_control, 2);
+ wpa_hexdump(MSG_DEBUG, "FT: FTE-MIC",
+ ftie->mic, sizeof(ftie->mic));
+ wpa_hexdump(MSG_DEBUG, "FT: FTE-ANonce",
+ ftie->anonce, WPA_NONCE_LEN);
+ wpa_hexdump(MSG_DEBUG, "FT: FTE-SNonce",
+ ftie->snonce, WPA_NONCE_LEN);
prot_ie_count = ftie->mic_control[1];
- if (wpa_ft_parse_ftie(pos, len, parse) < 0)
+ if (wpa_ft_parse_ftie(pos, len, parse, 0) < 0)
return -1;
break;
case WLAN_EID_TIMEOUT_INTERVAL:
+ wpa_hexdump(MSG_DEBUG, "FT: Timeout Interval",
+ pos, len);
if (len != 5)
break;
parse->tie = pos;
@@ -495,6 +1122,10 @@ static int rsn_key_mgmt_to_bitfield(const u8 *s)
return WPA_KEY_MGMT_FT_IEEE8021X;
if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_PSK)
return WPA_KEY_MGMT_FT_PSK;
+#ifdef CONFIG_SHA384
+ if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384)
+ return WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
+#endif /* CONFIG_SHA384 */
#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_IEEE80211W
if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SHA256)
@@ -512,6 +1143,22 @@ static int rsn_key_mgmt_to_bitfield(const u8 *s)
return WPA_KEY_MGMT_IEEE8021X_SUITE_B;
if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192)
return WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
+ if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FILS_SHA256)
+ return WPA_KEY_MGMT_FILS_SHA256;
+ if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FILS_SHA384)
+ return WPA_KEY_MGMT_FILS_SHA384;
+ if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_FILS_SHA256)
+ return WPA_KEY_MGMT_FT_FILS_SHA256;
+ if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_FILS_SHA384)
+ return WPA_KEY_MGMT_FT_FILS_SHA384;
+#ifdef CONFIG_OWE
+ if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_OWE)
+ return WPA_KEY_MGMT_OWE;
+#endif /* CONFIG_OWE */
+#ifdef CONFIG_DPP
+ if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_DPP)
+ return WPA_KEY_MGMT_DPP;
+#endif /* CONFIG_DPP */
if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_OSEN)
return WPA_KEY_MGMT_OSEN;
return 0;
@@ -581,6 +1228,9 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
pos = rsn_ie + 6;
left = rsn_ie_len - 6;
+ data->group_cipher = WPA_CIPHER_GTK_NOT_USED;
+ data->has_group = 1;
+ data->key_mgmt = WPA_KEY_MGMT_OSEN;
data->proto = WPA_PROTO_OSEN;
} else {
const struct rsn_ie_hdr *hdr;
@@ -601,6 +1251,7 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
if (left >= RSN_SELECTOR_LEN) {
data->group_cipher = rsn_selector_to_bitfield(pos);
+ data->has_group = 1;
if (!wpa_cipher_valid_group(data->group_cipher)) {
wpa_printf(MSG_DEBUG,
"%s: invalid group cipher 0x%x (%08x)",
@@ -626,6 +1277,8 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
"count %u left %u", __func__, count, left);
return -4;
}
+ if (count)
+ data->has_pairwise = 1;
for (i = 0; i < count; i++) {
data->pairwise_cipher |= rsn_selector_to_bitfield(pos);
pos += RSN_SELECTOR_LEN;
@@ -844,6 +1497,15 @@ int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len,
}
+int wpa_default_rsn_cipher(int freq)
+{
+ if (freq > 56160)
+ return WPA_CIPHER_GCMP; /* DMG */
+
+ return WPA_CIPHER_CCMP;
+}
+
+
#ifdef CONFIG_IEEE80211R
/**
@@ -851,27 +1513,39 @@ int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len,
*
* IEEE Std 802.11r-2008 - 8.5.1.5.3
*/
-void wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len,
- const u8 *ssid, size_t ssid_len,
- const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len,
- const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name)
+int wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len,
+ const u8 *ssid, size_t ssid_len,
+ const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len,
+ const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name,
+ int use_sha384)
{
u8 buf[1 + SSID_MAX_LEN + MOBILITY_DOMAIN_ID_LEN + 1 +
FT_R0KH_ID_MAX_LEN + ETH_ALEN];
- u8 *pos, r0_key_data[48], hash[32];
+ u8 *pos, r0_key_data[64], hash[48];
const u8 *addr[2];
size_t len[2];
+ size_t q = use_sha384 ? 48 : 32;
+ size_t r0_key_data_len = q + 16;
/*
* R0-Key-Data = KDF-384(XXKey, "FT-R0",
* SSIDlength || SSID || MDID || R0KHlength ||
* R0KH-ID || S0KH-ID)
- * XXKey is either the second 256 bits of MSK or PSK.
- * PMK-R0 = L(R0-Key-Data, 0, 256)
- * PMK-R0Name-Salt = L(R0-Key-Data, 256, 128)
+ * XXKey is either the second 256 bits of MSK or PSK; or the first
+ * 384 bits of MSK for FT-EAP-SHA384.
+ * PMK-R0 = L(R0-Key-Data, 0, Q)
+ * PMK-R0Name-Salt = L(R0-Key-Data, Q, 128)
+ * Q = 384 for FT-EAP-SHA384; otherwise, 256
*/
if (ssid_len > SSID_MAX_LEN || r0kh_id_len > FT_R0KH_ID_MAX_LEN)
- return;
+ return -1;
+ wpa_printf(MSG_DEBUG, "FT: Derive PMK-R0 using KDF-%s",
+ use_sha384 ? "SHA384" : "SHA256");
+ wpa_hexdump_key(MSG_DEBUG, "FT: XXKey", xxkey, xxkey_len);
+ wpa_hexdump_ascii(MSG_DEBUG, "FT: SSID", ssid, ssid_len);
+ wpa_hexdump(MSG_DEBUG, "FT: MDID", mdid, MOBILITY_DOMAIN_ID_LEN);
+ wpa_hexdump_ascii(MSG_DEBUG, "FT: R0KH-ID", r0kh_id, r0kh_id_len);
+ wpa_printf(MSG_DEBUG, "FT: S0KH-ID: " MACSTR, MAC2STR(s0kh_id));
pos = buf;
*pos++ = ssid_len;
os_memcpy(pos, ssid, ssid_len);
@@ -884,20 +1558,51 @@ void wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len,
os_memcpy(pos, s0kh_id, ETH_ALEN);
pos += ETH_ALEN;
- sha256_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf,
- r0_key_data, sizeof(r0_key_data));
- os_memcpy(pmk_r0, r0_key_data, PMK_LEN);
+#ifdef CONFIG_SHA384
+ if (use_sha384) {
+ if (xxkey_len != SHA384_MAC_LEN) {
+ wpa_printf(MSG_ERROR,
+ "FT: Unexpected XXKey length %d (expected %d)",
+ (int) xxkey_len, SHA384_MAC_LEN);
+ return -1;
+ }
+ if (sha384_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf,
+ r0_key_data, r0_key_data_len) < 0)
+ return -1;
+ }
+#endif /* CONFIG_SHA384 */
+ if (!use_sha384) {
+ if (xxkey_len != PMK_LEN) {
+ wpa_printf(MSG_ERROR,
+ "FT: Unexpected XXKey length %d (expected %d)",
+ (int) xxkey_len, PMK_LEN);
+ return -1;
+ }
+ if (sha256_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf,
+ r0_key_data, r0_key_data_len) < 0)
+ return -1;
+ }
+ os_memcpy(pmk_r0, r0_key_data, q);
+ wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", pmk_r0, q);
+ wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0Name-Salt", &r0_key_data[q], 16);
/*
- * PMKR0Name = Truncate-128(SHA-256("FT-R0N" || PMK-R0Name-Salt)
+ * PMKR0Name = Truncate-128(Hash("FT-R0N" || PMK-R0Name-Salt)
*/
addr[0] = (const u8 *) "FT-R0N";
len[0] = 6;
- addr[1] = r0_key_data + PMK_LEN;
+ addr[1] = &r0_key_data[q];
len[1] = 16;
- sha256_vector(2, addr, len, hash);
+#ifdef CONFIG_SHA384
+ if (use_sha384 && sha384_vector(2, addr, len, hash) < 0)
+ return -1;
+#endif /* CONFIG_SHA384 */
+ if (!use_sha384 && sha256_vector(2, addr, len, hash) < 0)
+ return -1;
os_memcpy(pmk_r0_name, hash, WPA_PMK_NAME_LEN);
+ os_memset(r0_key_data, 0, sizeof(r0_key_data));
+ return 0;
}
@@ -906,16 +1611,16 @@ void wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len,
*
* IEEE Std 802.11r-2008 - 8.5.1.5.4
*/
-void wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id,
- const u8 *s1kh_id, u8 *pmk_r1_name)
+int wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id,
+ const u8 *s1kh_id, u8 *pmk_r1_name, int use_sha384)
{
- u8 hash[32];
+ u8 hash[48];
const u8 *addr[4];
size_t len[4];
/*
- * PMKR1Name = Truncate-128(SHA-256("FT-R1N" || PMKR0Name ||
- * R1KH-ID || S1KH-ID))
+ * PMKR1Name = Truncate-128(Hash("FT-R1N" || PMKR0Name ||
+ * R1KH-ID || S1KH-ID))
*/
addr[0] = (const u8 *) "FT-R1N";
len[0] = 6;
@@ -926,8 +1631,14 @@ void wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id,
addr[3] = s1kh_id;
len[3] = ETH_ALEN;
- sha256_vector(4, addr, len, hash);
+#ifdef CONFIG_SHA384
+ if (use_sha384 && sha384_vector(4, addr, len, hash) < 0)
+ return -1;
+#endif /* CONFIG_SHA384 */
+ if (!use_sha384 && sha256_vector(4, addr, len, hash) < 0)
+ return -1;
os_memcpy(pmk_r1_name, hash, WPA_PMK_NAME_LEN);
+ return 0;
}
@@ -936,23 +1647,46 @@ void wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id,
*
* IEEE Std 802.11r-2008 - 8.5.1.5.4
*/
-void wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name,
- const u8 *r1kh_id, const u8 *s1kh_id,
- u8 *pmk_r1, u8 *pmk_r1_name)
+int wpa_derive_pmk_r1(const u8 *pmk_r0, size_t pmk_r0_len,
+ const u8 *pmk_r0_name,
+ const u8 *r1kh_id, const u8 *s1kh_id,
+ u8 *pmk_r1, u8 *pmk_r1_name)
{
u8 buf[FT_R1KH_ID_LEN + ETH_ALEN];
u8 *pos;
/* PMK-R1 = KDF-256(PMK-R0, "FT-R1", R1KH-ID || S1KH-ID) */
+ wpa_printf(MSG_DEBUG, "FT: Derive PMK-R1 using KDF-%s",
+ pmk_r0_len == SHA384_MAC_LEN ? "SHA384" : "SHA256");
+ wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", pmk_r0, pmk_r0_len);
+ wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID", r1kh_id, FT_R1KH_ID_LEN);
+ wpa_printf(MSG_DEBUG, "FT: S1KH-ID: " MACSTR, MAC2STR(s1kh_id));
pos = buf;
os_memcpy(pos, r1kh_id, FT_R1KH_ID_LEN);
pos += FT_R1KH_ID_LEN;
os_memcpy(pos, s1kh_id, ETH_ALEN);
pos += ETH_ALEN;
- sha256_prf(pmk_r0, PMK_LEN, "FT-R1", buf, pos - buf, pmk_r1, PMK_LEN);
+#ifdef CONFIG_SHA384
+ if (pmk_r0_len == SHA384_MAC_LEN &&
+ sha384_prf(pmk_r0, pmk_r0_len, "FT-R1",
+ buf, pos - buf, pmk_r1, pmk_r0_len) < 0)
+ return -1;
+#endif /* CONFIG_SHA384 */
+ if (pmk_r0_len == PMK_LEN &&
+ sha256_prf(pmk_r0, pmk_r0_len, "FT-R1",
+ buf, pos - buf, pmk_r1, pmk_r0_len) < 0)
+ return -1;
+ if (pmk_r0_len != SHA384_MAC_LEN && pmk_r0_len != PMK_LEN) {
+ wpa_printf(MSG_ERROR, "FT: Unexpected PMK-R0 length %d",
+ (int) pmk_r0_len);
+ return -1;
+ }
+ wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", pmk_r1, pmk_r0_len);
- wpa_derive_pmk_r1_name(pmk_r0_name, r1kh_id, s1kh_id, pmk_r1_name);
+ return wpa_derive_pmk_r1_name(pmk_r0_name, r1kh_id, s1kh_id,
+ pmk_r1_name,
+ pmk_r0_len == SHA384_MAC_LEN);
}
@@ -961,7 +1695,8 @@ void wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name,
*
* IEEE Std 802.11r-2008 - 8.5.1.5.5
*/
-int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce,
+int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, size_t pmk_r1_len,
+ const u8 *snonce, const u8 *anonce,
const u8 *sta_addr, const u8 *bssid,
const u8 *pmk_r1_name,
struct wpa_ptk *ptk, u8 *ptk_name, int akmp, int cipher)
@@ -970,13 +1705,21 @@ int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce,
u8 *pos, hash[32];
const u8 *addr[6];
size_t len[6];
- u8 tmp[WPA_KCK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN];
- size_t ptk_len;
+ u8 tmp[2 * WPA_KCK_MAX_LEN + 2 * WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN];
+ size_t ptk_len, offset;
+ int use_sha384 = wpa_key_mgmt_sha384(akmp);
/*
* PTK = KDF-PTKLen(PMK-R1, "FT-PTK", SNonce || ANonce ||
* BSSID || STA-ADDR)
*/
+ wpa_printf(MSG_DEBUG, "FT: Derive PTK using KDF-%s",
+ use_sha384 ? "SHA384" : "SHA256");
+ wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", pmk_r1, pmk_r1_len);
+ wpa_hexdump(MSG_DEBUG, "FT: SNonce", snonce, WPA_NONCE_LEN);
+ wpa_hexdump(MSG_DEBUG, "FT: ANonce", anonce, WPA_NONCE_LEN);
+ wpa_printf(MSG_DEBUG, "FT: BSSID=" MACSTR " STA-ADDR=" MACSTR,
+ MAC2STR(bssid), MAC2STR(sta_addr));
pos = buf;
os_memcpy(pos, snonce, WPA_NONCE_LEN);
pos += WPA_NONCE_LEN;
@@ -987,17 +1730,45 @@ int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce,
os_memcpy(pos, sta_addr, ETH_ALEN);
pos += ETH_ALEN;
- ptk->kck_len = wpa_kck_len(akmp);
- ptk->kek_len = wpa_kek_len(akmp);
+ ptk->kck_len = wpa_kck_len(akmp, PMK_LEN);
+ ptk->kck2_len = wpa_kck2_len(akmp);
+ ptk->kek_len = wpa_kek_len(akmp, PMK_LEN);
+ ptk->kek2_len = wpa_kek2_len(akmp);
ptk->tk_len = wpa_cipher_key_len(cipher);
- ptk_len = ptk->kck_len + ptk->kek_len + ptk->tk_len;
-
- sha256_prf(pmk_r1, PMK_LEN, "FT-PTK", buf, pos - buf, tmp, ptk_len);
+ ptk_len = ptk->kck_len + ptk->kek_len + ptk->tk_len +
+ ptk->kck2_len + ptk->kek2_len;
+
+#ifdef CONFIG_SHA384
+ if (use_sha384) {
+ if (pmk_r1_len != SHA384_MAC_LEN) {
+ wpa_printf(MSG_ERROR,
+ "FT: Unexpected PMK-R1 length %d (expected %d)",
+ (int) pmk_r1_len, SHA384_MAC_LEN);
+ return -1;
+ }
+ if (sha384_prf(pmk_r1, pmk_r1_len, "FT-PTK",
+ buf, pos - buf, tmp, ptk_len) < 0)
+ return -1;
+ }
+#endif /* CONFIG_SHA384 */
+ if (!use_sha384) {
+ if (pmk_r1_len != PMK_LEN) {
+ wpa_printf(MSG_ERROR,
+ "FT: Unexpected PMK-R1 length %d (expected %d)",
+ (int) pmk_r1_len, PMK_LEN);
+ return -1;
+ }
+ if (sha256_prf(pmk_r1, pmk_r1_len, "FT-PTK",
+ buf, pos - buf, tmp, ptk_len) < 0)
+ return -1;
+ }
+ wpa_hexdump_key(MSG_DEBUG, "FT: PTK", tmp, ptk_len);
/*
* PTKName = Truncate-128(SHA-256(PMKR1Name || "FT-PTKN" || SNonce ||
* ANonce || BSSID || STA-ADDR))
*/
+ wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", pmk_r1_name, WPA_PMK_NAME_LEN);
addr[0] = pmk_r1_name;
len[0] = WPA_PMK_NAME_LEN;
addr[1] = (const u8 *) "FT-PTKN";
@@ -1011,15 +1782,28 @@ int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce,
addr[5] = sta_addr;
len[5] = ETH_ALEN;
- sha256_vector(6, addr, len, hash);
+ if (sha256_vector(6, addr, len, hash) < 0)
+ return -1;
os_memcpy(ptk_name, hash, WPA_PMK_NAME_LEN);
os_memcpy(ptk->kck, tmp, ptk->kck_len);
- os_memcpy(ptk->kek, tmp + ptk->kck_len, ptk->kek_len);
- os_memcpy(ptk->tk, tmp + ptk->kck_len + ptk->kek_len, ptk->tk_len);
+ offset = ptk->kck_len;
+ os_memcpy(ptk->kek, tmp + offset, ptk->kek_len);
+ offset += ptk->kek_len;
+ os_memcpy(ptk->tk, tmp + offset, ptk->tk_len);
+ offset += ptk->tk_len;
+ os_memcpy(ptk->kck2, tmp + offset, ptk->kck2_len);
+ offset += ptk->kck2_len;
+ os_memcpy(ptk->kek2, tmp + offset, ptk->kek2_len);
wpa_hexdump_key(MSG_DEBUG, "FT: KCK", ptk->kck, ptk->kck_len);
wpa_hexdump_key(MSG_DEBUG, "FT: KEK", ptk->kek, ptk->kek_len);
+ if (ptk->kck2_len)
+ wpa_hexdump_key(MSG_DEBUG, "FT: KCK2",
+ ptk->kck2, ptk->kck2_len);
+ if (ptk->kek2_len)
+ wpa_hexdump_key(MSG_DEBUG, "FT: KEK2",
+ ptk->kek2, ptk->kek2_len);
wpa_hexdump_key(MSG_DEBUG, "FT: TK", ptk->tk, ptk->tk_len);
wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN);
@@ -1038,29 +1822,48 @@ int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce,
* @aa: Authenticator address
* @spa: Supplicant address
* @pmkid: Buffer for PMKID
- * @use_sha256: Whether to use SHA256-based KDF
+ * @akmp: Negotiated key management protocol
*
- * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
- * PMKID = HMAC-SHA1-128(PMK, "PMK Name" || AA || SPA)
+ * IEEE Std 802.11-2016 - 12.7.1.3 Pairwise key hierarchy
+ * AKM: 00-0F-AC:5, 00-0F-AC:6, 00-0F-AC:14, 00-0F-AC:16
+ * PMKID = Truncate-128(HMAC-SHA-256(PMK, "PMK Name" || AA || SPA))
+ * AKM: 00-0F-AC:11
+ * See rsn_pmkid_suite_b()
+ * AKM: 00-0F-AC:12
+ * See rsn_pmkid_suite_b_192()
+ * AKM: 00-0F-AC:13, 00-0F-AC:15, 00-0F-AC:17
+ * PMKID = Truncate-128(HMAC-SHA-384(PMK, "PMK Name" || AA || SPA))
+ * Otherwise:
+ * PMKID = Truncate-128(HMAC-SHA-1(PMK, "PMK Name" || AA || SPA))
*/
void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
- u8 *pmkid, int use_sha256)
+ u8 *pmkid, int akmp)
{
char *title = "PMK Name";
const u8 *addr[3];
const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
- unsigned char hash[SHA256_MAC_LEN];
+ unsigned char hash[SHA384_MAC_LEN];
addr[0] = (u8 *) title;
addr[1] = aa;
addr[2] = spa;
-#ifdef CONFIG_IEEE80211W
- if (use_sha256)
+ if (0) {
+#if defined(CONFIG_FILS) || defined(CONFIG_SHA384)
+ } else if (wpa_key_mgmt_sha384(akmp)) {
+ wpa_printf(MSG_DEBUG, "RSN: Derive PMKID using HMAC-SHA-384");
+ hmac_sha384_vector(pmk, pmk_len, 3, addr, len, hash);
+#endif /* CONFIG_FILS || CONFIG_SHA384 */
+#if defined(CONFIG_IEEE80211W) || defined(CONFIG_FILS)
+ } else if (wpa_key_mgmt_sha256(akmp)) {
+ wpa_printf(MSG_DEBUG, "RSN: Derive PMKID using HMAC-SHA-256");
hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash);
- else
-#endif /* CONFIG_IEEE80211W */
+#endif /* CONFIG_IEEE80211W || CONFIG_FILS */
+ } else {
+ wpa_printf(MSG_DEBUG, "RSN: Derive PMKID using HMAC-SHA-1");
hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash);
+ }
+ wpa_hexdump(MSG_DEBUG, "RSN: Derived PMKID", hash, PMKID_LEN);
os_memcpy(pmkid, hash, PMKID_LEN);
}
@@ -1157,6 +1960,14 @@ const char * wpa_cipher_txt(int cipher)
return "GCMP-256";
case WPA_CIPHER_CCMP_256:
return "CCMP-256";
+ case WPA_CIPHER_AES_128_CMAC:
+ return "BIP";
+ case WPA_CIPHER_BIP_GMAC_128:
+ return "BIP-GMAC-128";
+ case WPA_CIPHER_BIP_GMAC_256:
+ return "BIP-GMAC-256";
+ case WPA_CIPHER_BIP_CMAC_256:
+ return "BIP-CMAC-256";
case WPA_CIPHER_GTK_NOT_USED:
return "GTK_NOT_USED";
default:
@@ -1193,6 +2004,8 @@ const char * wpa_key_mgmt_txt(int key_mgmt, int proto)
#ifdef CONFIG_IEEE80211R
case WPA_KEY_MGMT_FT_IEEE8021X:
return "FT-EAP";
+ case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
+ return "FT-EAP-SHA384";
case WPA_KEY_MGMT_FT_PSK:
return "FT-PSK";
#endif /* CONFIG_IEEE80211R */
@@ -1214,6 +2027,18 @@ const char * wpa_key_mgmt_txt(int key_mgmt, int proto)
return "WPA2-EAP-SUITE-B";
case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
return "WPA2-EAP-SUITE-B-192";
+ case WPA_KEY_MGMT_FILS_SHA256:
+ return "FILS-SHA256";
+ case WPA_KEY_MGMT_FILS_SHA384:
+ return "FILS-SHA384";
+ case WPA_KEY_MGMT_FT_FILS_SHA256:
+ return "FT-FILS-SHA256";
+ case WPA_KEY_MGMT_FT_FILS_SHA384:
+ return "FT-FILS-SHA384";
+ case WPA_KEY_MGMT_OWE:
+ return "OWE";
+ case WPA_KEY_MGMT_DPP:
+ return "DPP";
default:
return "UNKNOWN";
}
@@ -1222,28 +2047,36 @@ const char * wpa_key_mgmt_txt(int key_mgmt, int proto)
u32 wpa_akm_to_suite(int akm)
{
+ if (akm & WPA_KEY_MGMT_FT_IEEE8021X_SHA384)
+ return RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384;
if (akm & WPA_KEY_MGMT_FT_IEEE8021X)
- return WLAN_AKM_SUITE_FT_8021X;
+ return RSN_AUTH_KEY_MGMT_FT_802_1X;
if (akm & WPA_KEY_MGMT_FT_PSK)
- return WLAN_AKM_SUITE_FT_PSK;
- if (akm & WPA_KEY_MGMT_IEEE8021X)
- return WLAN_AKM_SUITE_8021X;
+ return RSN_AUTH_KEY_MGMT_FT_PSK;
if (akm & WPA_KEY_MGMT_IEEE8021X_SHA256)
- return WLAN_AKM_SUITE_8021X_SHA256;
+ return RSN_AUTH_KEY_MGMT_802_1X_SHA256;
if (akm & WPA_KEY_MGMT_IEEE8021X)
- return WLAN_AKM_SUITE_8021X;
+ return RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
if (akm & WPA_KEY_MGMT_PSK_SHA256)
- return WLAN_AKM_SUITE_PSK_SHA256;
+ return RSN_AUTH_KEY_MGMT_PSK_SHA256;
if (akm & WPA_KEY_MGMT_PSK)
- return WLAN_AKM_SUITE_PSK;
+ return RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X;
if (akm & WPA_KEY_MGMT_CCKM)
- return WLAN_AKM_SUITE_CCKM;
+ return RSN_AUTH_KEY_MGMT_CCKM;
if (akm & WPA_KEY_MGMT_OSEN)
- return WLAN_AKM_SUITE_OSEN;
+ return RSN_AUTH_KEY_MGMT_OSEN;
if (akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
- return WLAN_AKM_SUITE_8021X_SUITE_B;
+ return RSN_AUTH_KEY_MGMT_802_1X_SUITE_B;
if (akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
- return WLAN_AKM_SUITE_8021X_SUITE_B_192;
+ return RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192;
+ if (akm & WPA_KEY_MGMT_FILS_SHA256)
+ return RSN_AUTH_KEY_MGMT_FILS_SHA256;
+ if (akm & WPA_KEY_MGMT_FILS_SHA384)
+ return RSN_AUTH_KEY_MGMT_FILS_SHA384;
+ if (akm & WPA_KEY_MGMT_FT_FILS_SHA256)
+ return RSN_AUTH_KEY_MGMT_FT_FILS_SHA256;
+ if (akm & WPA_KEY_MGMT_FT_FILS_SHA384)
+ return RSN_AUTH_KEY_MGMT_FT_FILS_SHA384;
return 0;
}
@@ -1285,7 +2118,7 @@ int wpa_compare_rsn_ie(int ft_initial_assoc,
}
-#ifdef CONFIG_IEEE80211R
+#if defined(CONFIG_IEEE80211R) || defined(CONFIG_FILS)
int wpa_insert_pmkid(u8 *ies, size_t *ies_len, const u8 *pmkid)
{
u8 *start, *end, *rpos, *rend;
@@ -1384,7 +2217,7 @@ int wpa_insert_pmkid(u8 *ies, size_t *ies_len, const u8 *pmkid)
return 0;
}
-#endif /* CONFIG_IEEE80211R */
+#endif /* CONFIG_IEEE80211R || CONFIG_FILS */
int wpa_cipher_key_len(int cipher)
@@ -1423,7 +2256,7 @@ int wpa_cipher_rsc_len(int cipher)
}
-int wpa_cipher_to_alg(int cipher)
+enum wpa_alg wpa_cipher_to_alg(int cipher)
{
switch (cipher) {
case WPA_CIPHER_CCMP_256:
@@ -1618,6 +2451,14 @@ int wpa_parse_cipher(const char *value)
val |= WPA_CIPHER_NONE;
else if (os_strcmp(start, "GTK_NOT_USED") == 0)
val |= WPA_CIPHER_GTK_NOT_USED;
+ else if (os_strcmp(start, "AES-128-CMAC") == 0)
+ val |= WPA_CIPHER_AES_128_CMAC;
+ else if (os_strcmp(start, "BIP-GMAC-128") == 0)
+ val |= WPA_CIPHER_BIP_GMAC_128;
+ else if (os_strcmp(start, "BIP-GMAC-256") == 0)
+ val |= WPA_CIPHER_BIP_GMAC_256;
+ else if (os_strcmp(start, "BIP-CMAC-256") == 0)
+ val |= WPA_CIPHER_BIP_CMAC_256;
else {
os_free(buf);
return -1;
@@ -1673,6 +2514,34 @@ int wpa_write_ciphers(char *start, char *end, int ciphers, const char *delim)
return -1;
pos += ret;
}
+ if (ciphers & WPA_CIPHER_AES_128_CMAC) {
+ ret = os_snprintf(pos, end - pos, "%sAES-128-CMAC",
+ pos == start ? "" : delim);
+ if (os_snprintf_error(end - pos, ret))
+ return -1;
+ pos += ret;
+ }
+ if (ciphers & WPA_CIPHER_BIP_GMAC_128) {
+ ret = os_snprintf(pos, end - pos, "%sBIP-GMAC-128",
+ pos == start ? "" : delim);
+ if (os_snprintf_error(end - pos, ret))
+ return -1;
+ pos += ret;
+ }
+ if (ciphers & WPA_CIPHER_BIP_GMAC_256) {
+ ret = os_snprintf(pos, end - pos, "%sBIP-GMAC-256",
+ pos == start ? "" : delim);
+ if (os_snprintf_error(end - pos, ret))
+ return -1;
+ pos += ret;
+ }
+ if (ciphers & WPA_CIPHER_BIP_CMAC_256) {
+ ret = os_snprintf(pos, end - pos, "%sBIP-CMAC-256",
+ pos == start ? "" : delim);
+ if (os_snprintf_error(end - pos, ret))
+ return -1;
+ pos += ret;
+ }
if (ciphers & WPA_CIPHER_NONE) {
ret = os_snprintf(pos, end - pos, "%sNONE",
pos == start ? "" : delim);
@@ -1707,3 +2576,29 @@ int wpa_select_ap_group_cipher(int wpa, int wpa_pairwise, int rsn_pairwise)
return WPA_CIPHER_CCMP_256;
return WPA_CIPHER_CCMP;
}
+
+
+#ifdef CONFIG_FILS
+int fils_domain_name_hash(const char *domain, u8 *hash)
+{
+ char buf[255], *wpos = buf;
+ const char *pos = domain;
+ size_t len;
+ const u8 *addr[1];
+ u8 mac[SHA256_MAC_LEN];
+
+ for (len = 0; len < sizeof(buf) && *pos; len++) {
+ if (isalpha(*pos) && isupper(*pos))
+ *wpos++ = tolower(*pos);
+ else
+ *wpos++ = *pos;
+ pos++;
+ }
+
+ addr[0] = (const u8 *) buf;
+ if (sha256_vector(1, addr, &len, mac) < 0)
+ return -1;
+ os_memcpy(hash, mac, 2);
+ return 0;
+}
+#endif /* CONFIG_FILS */
diff --git a/freebsd/contrib/wpa/src/common/wpa_common.h b/freebsd/contrib/wpa/src/common/wpa_common.h
index 1021ccb0..e83d6887 100644
--- a/freebsd/contrib/wpa/src/common/wpa_common.h
+++ b/freebsd/contrib/wpa/src/common/wpa_common.h
@@ -1,6 +1,6 @@
/*
* WPA definitions shared between hostapd and wpa_supplicant
- * Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2018, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -13,13 +13,15 @@
#define PMKID_LEN 16
#define PMK_LEN 32
#define PMK_LEN_SUITE_B_192 48
-#define PMK_LEN_MAX 48
+#define PMK_LEN_MAX 64
#define WPA_REPLAY_COUNTER_LEN 8
#define WPA_NONCE_LEN 32
#define WPA_KEY_RSC_LEN 8
#define WPA_GMK_LEN 32
#define WPA_GTK_MAX_LEN 32
+#define OWE_DH_GROUP 19
+
#define WPA_ALLOWED_PAIRWISE_CIPHERS \
(WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | WPA_CIPHER_TKIP | WPA_CIPHER_NONE | \
WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP_256)
@@ -27,6 +29,9 @@ WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP_256)
(WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | WPA_CIPHER_TKIP | \
WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP_256 | \
WPA_CIPHER_GTK_NOT_USED)
+#define WPA_ALLOWED_GROUP_MGMT_CIPHERS \
+(WPA_CIPHER_AES_128_CMAC | WPA_CIPHER_BIP_GMAC_128 | WPA_CIPHER_BIP_GMAC_256 | \
+WPA_CIPHER_BIP_CMAC_256)
#define WPA_SELECTOR_LEN 4
#define WPA_VERSION 1
@@ -48,10 +53,8 @@ WPA_CIPHER_GTK_NOT_USED)
#define RSN_AUTH_KEY_MGMT_UNSPEC_802_1X RSN_SELECTOR(0x00, 0x0f, 0xac, 1)
#define RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X RSN_SELECTOR(0x00, 0x0f, 0xac, 2)
-#ifdef CONFIG_IEEE80211R
#define RSN_AUTH_KEY_MGMT_FT_802_1X RSN_SELECTOR(0x00, 0x0f, 0xac, 3)
#define RSN_AUTH_KEY_MGMT_FT_PSK RSN_SELECTOR(0x00, 0x0f, 0xac, 4)
-#endif /* CONFIG_IEEE80211R */
#define RSN_AUTH_KEY_MGMT_802_1X_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 5)
#define RSN_AUTH_KEY_MGMT_PSK_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 6)
#define RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE RSN_SELECTOR(0x00, 0x0f, 0xac, 7)
@@ -59,17 +62,24 @@ WPA_CIPHER_GTK_NOT_USED)
#define RSN_AUTH_KEY_MGMT_FT_SAE RSN_SELECTOR(0x00, 0x0f, 0xac, 9)
#define RSN_AUTH_KEY_MGMT_802_1X_SUITE_B RSN_SELECTOR(0x00, 0x0f, 0xac, 11)
#define RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192 RSN_SELECTOR(0x00, 0x0f, 0xac, 12)
-#define RSN_AUTH_KEY_MGMT_FT_802_1X_SUITE_B_192 \
-RSN_SELECTOR(0x00, 0x0f, 0xac, 13)
+#define RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384 RSN_SELECTOR(0x00, 0x0f, 0xac, 13)
+#define RSN_AUTH_KEY_MGMT_FILS_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 14)
+#define RSN_AUTH_KEY_MGMT_FILS_SHA384 RSN_SELECTOR(0x00, 0x0f, 0xac, 15)
+#define RSN_AUTH_KEY_MGMT_FT_FILS_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 16)
+#define RSN_AUTH_KEY_MGMT_FT_FILS_SHA384 RSN_SELECTOR(0x00, 0x0f, 0xac, 17)
+#define RSN_AUTH_KEY_MGMT_OWE RSN_SELECTOR(0x00, 0x0f, 0xac, 18)
#define RSN_AUTH_KEY_MGMT_CCKM RSN_SELECTOR(0x00, 0x40, 0x96, 0x00)
#define RSN_AUTH_KEY_MGMT_OSEN RSN_SELECTOR(0x50, 0x6f, 0x9a, 0x01)
+#define RSN_AUTH_KEY_MGMT_DPP RSN_SELECTOR(0x50, 0x6f, 0x9a, 0x02)
#define RSN_CIPHER_SUITE_NONE RSN_SELECTOR(0x00, 0x0f, 0xac, 0)
+#define RSN_CIPHER_SUITE_WEP40 RSN_SELECTOR(0x00, 0x0f, 0xac, 1)
#define RSN_CIPHER_SUITE_TKIP RSN_SELECTOR(0x00, 0x0f, 0xac, 2)
#if 0
#define RSN_CIPHER_SUITE_WRAP RSN_SELECTOR(0x00, 0x0f, 0xac, 3)
#endif
#define RSN_CIPHER_SUITE_CCMP RSN_SELECTOR(0x00, 0x0f, 0xac, 4)
+#define RSN_CIPHER_SUITE_WEP104 RSN_SELECTOR(0x00, 0x0f, 0xac, 5)
#define RSN_CIPHER_SUITE_AES_128_CMAC RSN_SELECTOR(0x00, 0x0f, 0xac, 6)
#define RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED RSN_SELECTOR(0x00, 0x0f, 0xac, 7)
#define RSN_CIPHER_SUITE_GCMP RSN_SELECTOR(0x00, 0x0f, 0xac, 8)
@@ -78,6 +88,12 @@ RSN_SELECTOR(0x00, 0x0f, 0xac, 13)
#define RSN_CIPHER_SUITE_BIP_GMAC_128 RSN_SELECTOR(0x00, 0x0f, 0xac, 11)
#define RSN_CIPHER_SUITE_BIP_GMAC_256 RSN_SELECTOR(0x00, 0x0f, 0xac, 12)
#define RSN_CIPHER_SUITE_BIP_CMAC_256 RSN_SELECTOR(0x00, 0x0f, 0xac, 13)
+#define RSN_CIPHER_SUITE_SMS4 RSN_SELECTOR(0x00, 0x14, 0x72, 1)
+#define RSN_CIPHER_SUITE_CKIP RSN_SELECTOR(0x00, 0x40, 0x96, 0)
+#define RSN_CIPHER_SUITE_CKIP_CMIC RSN_SELECTOR(0x00, 0x40, 0x96, 1)
+#define RSN_CIPHER_SUITE_CMIC RSN_SELECTOR(0x00, 0x40, 0x96, 2)
+/* KRK is defined for nl80211 use only */
+#define RSN_CIPHER_SUITE_KRK RSN_SELECTOR(0x00, 0x40, 0x96, 255)
/* EAPOL-Key Key Data Encapsulation
* GroupKey and PeerKey require encryption, otherwise, encryption is optional.
@@ -88,18 +104,13 @@ RSN_SELECTOR(0x00, 0x0f, 0xac, 13)
#endif
#define RSN_KEY_DATA_MAC_ADDR RSN_SELECTOR(0x00, 0x0f, 0xac, 3)
#define RSN_KEY_DATA_PMKID RSN_SELECTOR(0x00, 0x0f, 0xac, 4)
-#ifdef CONFIG_PEERKEY
-#define RSN_KEY_DATA_SMK RSN_SELECTOR(0x00, 0x0f, 0xac, 5)
-#define RSN_KEY_DATA_NONCE RSN_SELECTOR(0x00, 0x0f, 0xac, 6)
-#define RSN_KEY_DATA_LIFETIME RSN_SELECTOR(0x00, 0x0f, 0xac, 7)
-#define RSN_KEY_DATA_ERROR RSN_SELECTOR(0x00, 0x0f, 0xac, 8)
-#endif /* CONFIG_PEERKEY */
#ifdef CONFIG_IEEE80211W
#define RSN_KEY_DATA_IGTK RSN_SELECTOR(0x00, 0x0f, 0xac, 9)
#endif /* CONFIG_IEEE80211W */
#define RSN_KEY_DATA_KEYID RSN_SELECTOR(0x00, 0x0f, 0xac, 10)
#define RSN_KEY_DATA_MULTIBAND_GTK RSN_SELECTOR(0x00, 0x0f, 0xac, 11)
#define RSN_KEY_DATA_MULTIBAND_KEYID RSN_SELECTOR(0x00, 0x0f, 0xac, 12)
+#define RSN_KEY_DATA_OCI RSN_SELECTOR(0x00, 0x0f, 0xac, 13)
#define WFA_KEY_DATA_IP_ADDR_REQ RSN_SELECTOR(0x50, 0x6f, 0x9a, 4)
#define WFA_KEY_DATA_IP_ADDR_ALLOC RSN_SELECTOR(0x50, 0x6f, 0x9a, 5)
@@ -138,7 +149,8 @@ RSN_SELECTOR(0x00, 0x0f, 0xac, 13)
#define WPA_CAPABILITY_SPP_A_MSDU_REQUIRED BIT(11)
#define WPA_CAPABILITY_PBAC BIT(12)
#define WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST BIT(13)
-/* B14-B15: Reserved */
+#define WPA_CAPABILITY_OCVC BIT(14)
+/* B15: Reserved */
/* IEEE 802.11r */
@@ -179,30 +191,17 @@ struct wpa_eapol_key {
u8 key_iv[16];
u8 key_rsc[WPA_KEY_RSC_LEN];
u8 key_id[8]; /* Reserved in IEEE 802.11i/RSN */
- u8 key_mic[16];
- u8 key_data_length[2]; /* big endian */
- /* followed by key_data_length bytes of key_data */
-} STRUCT_PACKED;
-
-struct wpa_eapol_key_192 {
- u8 type;
- /* Note: key_info, key_length, and key_data_length are unaligned */
- u8 key_info[2]; /* big endian */
- u8 key_length[2]; /* big endian */
- u8 replay_counter[WPA_REPLAY_COUNTER_LEN];
- u8 key_nonce[WPA_NONCE_LEN];
- u8 key_iv[16];
- u8 key_rsc[WPA_KEY_RSC_LEN];
- u8 key_id[8]; /* Reserved in IEEE 802.11i/RSN */
- u8 key_mic[24];
- u8 key_data_length[2]; /* big endian */
- /* followed by key_data_length bytes of key_data */
+ /* variable length Key MIC field */
+ /* big endian 2-octet Key Data Length field */
+ /* followed by Key Data Length bytes of Key Data */
} STRUCT_PACKED;
-#define WPA_EAPOL_KEY_MIC_MAX_LEN 24
-#define WPA_KCK_MAX_LEN 24
-#define WPA_KEK_MAX_LEN 32
+#define WPA_EAPOL_KEY_MIC_MAX_LEN 32
+#define WPA_KCK_MAX_LEN 32
+#define WPA_KEK_MAX_LEN 64
#define WPA_TK_MAX_LEN 32
+#define FILS_ICK_MAX_LEN 48
+#define FILS_FT_MAX_LEN 48
/**
* struct wpa_ptk - WPA Pairwise Transient Key
@@ -212,9 +211,13 @@ struct wpa_ptk {
u8 kck[WPA_KCK_MAX_LEN]; /* EAPOL-Key Key Confirmation Key (KCK) */
u8 kek[WPA_KEK_MAX_LEN]; /* EAPOL-Key Key Encryption Key (KEK) */
u8 tk[WPA_TK_MAX_LEN]; /* Temporal Key (TK) */
+ u8 kck2[WPA_KCK_MAX_LEN]; /* FT reasoc Key Confirmation Key (KCK2) */
+ u8 kek2[WPA_KEK_MAX_LEN]; /* FT reassoc Key Encryption Key (KEK2) */
size_t kck_len;
size_t kek_len;
size_t tk_len;
+ size_t kck2_len;
+ size_t kek2_len;
int installed; /* 1 if key has already been installed to driver */
};
@@ -283,22 +286,6 @@ struct rsn_ie_hdr {
} STRUCT_PACKED;
-#ifdef CONFIG_PEERKEY
-enum {
- STK_MUI_4WAY_STA_AP = 1,
- STK_MUI_4WAY_STAT_STA = 2,
- STK_MUI_GTK = 3,
- STK_MUI_SMK = 4
-};
-
-enum {
- STK_ERR_STA_NR = 1,
- STK_ERR_STA_NRSN = 2,
- STK_ERR_CPHR_NS = 3,
- STK_ERR_NO_STSL = 4
-};
-#endif /* CONFIG_PEERKEY */
-
struct rsn_error_kde {
be16 mui;
be16 error_type;
@@ -329,10 +316,19 @@ struct rsn_ftie {
/* followed by optional parameters */
} STRUCT_PACKED;
+struct rsn_ftie_sha384 {
+ u8 mic_control[2];
+ u8 mic[24];
+ u8 anonce[WPA_NONCE_LEN];
+ u8 snonce[WPA_NONCE_LEN];
+ /* followed by optional parameters */
+} STRUCT_PACKED;
+
#define FTIE_SUBELEM_R1KH_ID 1
#define FTIE_SUBELEM_GTK 2
#define FTIE_SUBELEM_R0KH_ID 3
#define FTIE_SUBELEM_IGTK 4
+#define FTIE_SUBELEM_OCI 5
struct rsn_rdie {
u8 id;
@@ -351,7 +347,24 @@ int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver,
int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label,
const u8 *addr1, const u8 *addr2,
const u8 *nonce1, const u8 *nonce2,
- struct wpa_ptk *ptk, int akmp, int cipher);
+ struct wpa_ptk *ptk, int akmp, int cipher,
+ const u8 *z, size_t z_len);
+int fils_rmsk_to_pmk(int akmp, const u8 *rmsk, size_t rmsk_len,
+ const u8 *snonce, const u8 *anonce, const u8 *dh_ss,
+ size_t dh_ss_len, u8 *pmk, size_t *pmk_len);
+int fils_pmkid_erp(int akmp, const u8 *reauth, size_t reauth_len,
+ u8 *pmkid);
+int fils_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const u8 *spa, const u8 *aa,
+ const u8 *snonce, const u8 *anonce, const u8 *dhss,
+ size_t dhss_len, struct wpa_ptk *ptk,
+ u8 *ick, size_t *ick_len, int akmp, int cipher,
+ u8 *fils_ft, size_t *fils_ft_len);
+int fils_key_auth_sk(const u8 *ick, size_t ick_len, const u8 *snonce,
+ const u8 *anonce, const u8 *sta_addr, const u8 *bssid,
+ const u8 *g_sta, size_t g_sta_len,
+ const u8 *g_ap, size_t g_ap_len,
+ int akmp, u8 *key_auth_sta, u8 *key_auth_ap,
+ size_t *key_auth_len);
#ifdef CONFIG_IEEE80211R
int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr,
@@ -360,17 +373,19 @@ int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr,
const u8 *ftie, size_t ftie_len,
const u8 *rsnie, size_t rsnie_len,
const u8 *ric, size_t ric_len, u8 *mic);
-void wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len,
- const u8 *ssid, size_t ssid_len,
- const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len,
- const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name);
-void wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id,
- const u8 *s1kh_id, u8 *pmk_r1_name);
-void wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name,
- const u8 *r1kh_id, const u8 *s1kh_id,
- u8 *pmk_r1, u8 *pmk_r1_name);
-int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce,
- const u8 *sta_addr, const u8 *bssid,
+int wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len,
+ const u8 *ssid, size_t ssid_len,
+ const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len,
+ const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name,
+ int use_sha384);
+int wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id,
+ const u8 *s1kh_id, u8 *pmk_r1_name, int use_sha384);
+int wpa_derive_pmk_r1(const u8 *pmk_r0, size_t pmk_r0_len,
+ const u8 *pmk_r0_name,
+ const u8 *r1kh_id, const u8 *s1kh_id,
+ u8 *pmk_r1, u8 *pmk_r1_name);
+int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, size_t pmk_r1_len, const u8 *snonce,
+ const u8 *anonce, const u8 *sta_addr, const u8 *bssid,
const u8 *pmk_r1_name,
struct wpa_ptk *ptk, u8 *ptk_name, int akmp, int cipher);
#endif /* CONFIG_IEEE80211R */
@@ -378,7 +393,9 @@ int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce,
struct wpa_ie_data {
int proto;
int pairwise_cipher;
+ int has_pairwise;
int group_cipher;
+ int has_group;
int key_mgmt;
int capabilities;
size_t num_pmkid;
@@ -391,9 +408,10 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
struct wpa_ie_data *data);
int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len,
struct wpa_ie_data *data);
+int wpa_default_rsn_cipher(int freq);
void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
- u8 *pmkid, int use_sha256);
+ u8 *pmkid, int akmp);
#ifdef CONFIG_SUITEB
int rsn_pmkid_suite_b(const u8 *kck, size_t kck_len, const u8 *aa,
const u8 *spa, u8 *pmkid);
@@ -440,15 +458,22 @@ struct wpa_ft_ies {
size_t tie_len;
const u8 *igtk;
size_t igtk_len;
+#ifdef CONFIG_OCV
+ const u8 *oci;
+ size_t oci_len;
+#endif /* CONFIG_OCV */
const u8 *ric;
size_t ric_len;
+ int key_mgmt;
+ int pairwise_cipher;
};
-int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse);
+int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse,
+ int use_sha384);
int wpa_cipher_key_len(int cipher);
int wpa_cipher_rsc_len(int cipher);
-int wpa_cipher_to_alg(int cipher);
+enum wpa_alg wpa_cipher_to_alg(int cipher);
int wpa_cipher_valid_group(int cipher);
int wpa_cipher_valid_pairwise(int cipher);
int wpa_cipher_valid_mgmt_group(int cipher);
@@ -460,6 +485,10 @@ int wpa_pick_group_cipher(int ciphers);
int wpa_parse_cipher(const char *value);
int wpa_write_ciphers(char *start, char *end, int ciphers, const char *delim);
int wpa_select_ap_group_cipher(int wpa, int wpa_pairwise, int rsn_pairwise);
-unsigned int wpa_mic_len(int akmp);
+unsigned int wpa_mic_len(int akmp, size_t pmk_len);
+int wpa_use_akm_defined(int akmp);
+int wpa_use_cmac(int akmp);
+int wpa_use_aes_key_wrap(int akmp);
+int fils_domain_name_hash(const char *domain, u8 *hash);
#endif /* WPA_COMMON_H */
diff --git a/freebsd/contrib/wpa/src/common/wpa_ctrl.h b/freebsd/contrib/wpa/src/common/wpa_ctrl.h
index 4dcba81d..f65077e0 100644
--- a/freebsd/contrib/wpa/src/common/wpa_ctrl.h
+++ b/freebsd/contrib/wpa/src/common/wpa_ctrl.h
@@ -1,6 +1,6 @@
/*
* wpa_supplicant/hostapd control interface library
- * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2017, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -50,10 +50,19 @@ extern "C" {
#define WPA_EVENT_EAP_TLS_CERT_ERROR "CTRL-EVENT-EAP-TLS-CERT-ERROR "
/** EAP status */
#define WPA_EVENT_EAP_STATUS "CTRL-EVENT-EAP-STATUS "
+/** Retransmit the previous request packet */
+#define WPA_EVENT_EAP_RETRANSMIT "CTRL-EVENT-EAP-RETRANSMIT "
+#define WPA_EVENT_EAP_RETRANSMIT2 "CTRL-EVENT-EAP-RETRANSMIT2 "
/** EAP authentication completed successfully */
#define WPA_EVENT_EAP_SUCCESS "CTRL-EVENT-EAP-SUCCESS "
+#define WPA_EVENT_EAP_SUCCESS2 "CTRL-EVENT-EAP-SUCCESS2 "
/** EAP authentication failed (EAP-Failure received) */
#define WPA_EVENT_EAP_FAILURE "CTRL-EVENT-EAP-FAILURE "
+#define WPA_EVENT_EAP_FAILURE2 "CTRL-EVENT-EAP-FAILURE2 "
+/** EAP authentication failed due to no response received */
+#define WPA_EVENT_EAP_TIMEOUT_FAILURE "CTRL-EVENT-EAP-TIMEOUT-FAILURE "
+#define WPA_EVENT_EAP_TIMEOUT_FAILURE2 "CTRL-EVENT-EAP-TIMEOUT-FAILURE2 "
+#define WPA_EVENT_EAP_ERROR_CODE "EAP-ERROR-CODE "
/** Network block temporarily disabled (e.g., due to authentication failure) */
#define WPA_EVENT_TEMP_DISABLED "CTRL-EVENT-SSID-TEMP-DISABLED "
/** Temporarily disabled network block re-enabled */
@@ -74,10 +83,15 @@ extern "C" {
#define WPA_EVENT_NETWORK_NOT_FOUND "CTRL-EVENT-NETWORK-NOT-FOUND "
/** Change in the signal level was reported by the driver */
#define WPA_EVENT_SIGNAL_CHANGE "CTRL-EVENT-SIGNAL-CHANGE "
+/** Beacon loss reported by the driver */
+#define WPA_EVENT_BEACON_LOSS "CTRL-EVENT-BEACON-LOSS "
/** Regulatory domain channel */
#define WPA_EVENT_REGDOM_CHANGE "CTRL-EVENT-REGDOM-CHANGE "
/** Channel switch (followed by freq=<MHz> and other channel parameters) */
#define WPA_EVENT_CHANNEL_SWITCH "CTRL-EVENT-CHANNEL-SWITCH "
+/** SAE authentication failed due to unknown password identifier */
+#define WPA_EVENT_SAE_UNKNOWN_PASSWORD_IDENTIFIER \
+ "CTRL-EVENT-SAE-UNKNOWN-PASSWORD-IDENTIFIER "
/** IP subnet status change notification
*
@@ -141,6 +155,33 @@ extern "C" {
#define WPS_EVENT_ER_AP_SETTINGS "WPS-ER-AP-SETTINGS "
#define WPS_EVENT_ER_SET_SEL_REG "WPS-ER-AP-SET-SEL-REG "
+/* DPP events */
+#define DPP_EVENT_AUTH_SUCCESS "DPP-AUTH-SUCCESS "
+#define DPP_EVENT_AUTH_INIT_FAILED "DPP-AUTH-INIT-FAILED "
+#define DPP_EVENT_NOT_COMPATIBLE "DPP-NOT-COMPATIBLE "
+#define DPP_EVENT_RESPONSE_PENDING "DPP-RESPONSE-PENDING "
+#define DPP_EVENT_SCAN_PEER_QR_CODE "DPP-SCAN-PEER-QR-CODE "
+#define DPP_EVENT_AUTH_DIRECTION "DPP-AUTH-DIRECTION "
+#define DPP_EVENT_CONF_RECEIVED "DPP-CONF-RECEIVED "
+#define DPP_EVENT_CONF_SENT "DPP-CONF-SENT "
+#define DPP_EVENT_CONF_FAILED "DPP-CONF-FAILED "
+#define DPP_EVENT_CONFOBJ_AKM "DPP-CONFOBJ-AKM "
+#define DPP_EVENT_CONFOBJ_SSID "DPP-CONFOBJ-SSID "
+#define DPP_EVENT_CONFOBJ_PASS "DPP-CONFOBJ-PASS "
+#define DPP_EVENT_CONFOBJ_PSK "DPP-CONFOBJ-PSK "
+#define DPP_EVENT_CONNECTOR "DPP-CONNECTOR "
+#define DPP_EVENT_C_SIGN_KEY "DPP-C-SIGN-KEY "
+#define DPP_EVENT_NET_ACCESS_KEY "DPP-NET-ACCESS-KEY "
+#define DPP_EVENT_MISSING_CONNECTOR "DPP-MISSING-CONNECTOR "
+#define DPP_EVENT_NETWORK_ID "DPP-NETWORK-ID "
+#define DPP_EVENT_RX "DPP-RX "
+#define DPP_EVENT_TX "DPP-TX "
+#define DPP_EVENT_TX_STATUS "DPP-TX-STATUS "
+#define DPP_EVENT_FAIL "DPP-FAIL "
+#define DPP_EVENT_PKEX_T_LIMIT "DPP-PKEX-T-LIMIT "
+#define DPP_EVENT_INTRO "DPP-INTRO "
+#define DPP_EVENT_CONF_REQ_RX "DPP-CONF-REQ-RX "
+
/* MESH events */
#define MESH_GROUP_STARTED "MESH-GROUP-STARTED "
#define MESH_GROUP_REMOVED "MESH-GROUP-REMOVED "
@@ -232,9 +273,14 @@ extern "C" {
#define RX_HS20_ANQP "RX-HS20-ANQP "
#define RX_HS20_ANQP_ICON "RX-HS20-ANQP-ICON "
#define RX_HS20_ICON "RX-HS20-ICON "
+#define RX_MBO_ANQP "RX-MBO-ANQP "
+
+/* parameters: <Venue Number> <Venue URL> */
+#define RX_VENUE_URL "RX-VENUE-URL "
#define HS20_SUBSCRIPTION_REMEDIATION "HS20-SUBSCRIPTION-REMEDIATION "
#define HS20_DEAUTH_IMMINENT_NOTICE "HS20-DEAUTH-IMMINENT-NOTICE "
+#define HS20_T_C_ACCEPTANCE "HS20-T-C-ACCEPTANCE "
#define EXT_RADIO_WORK_START "EXT-RADIO-WORK-START "
#define EXT_RADIO_WORK_TIMEOUT "EXT-RADIO-WORK-TIMEOUT "
@@ -258,6 +304,9 @@ extern "C" {
#define AP_REJECTED_MAX_STA "AP-REJECTED-MAX-STA "
#define AP_REJECTED_BLOCKED_STA "AP-REJECTED-BLOCKED-STA "
+#define HS20_T_C_FILTERING_ADD "HS20-T-C-FILTERING-ADD "
+#define HS20_T_C_FILTERING_REMOVE "HS20-T-C-FILTERING-REMOVE "
+
#define AP_EVENT_ENABLED "AP-ENABLED "
#define AP_EVENT_DISABLED "AP-DISABLED "
@@ -273,6 +322,7 @@ extern "C" {
#define DFS_EVENT_CAC_START "DFS-CAC-START "
#define DFS_EVENT_CAC_COMPLETED "DFS-CAC-COMPLETED "
#define DFS_EVENT_NOP_FINISHED "DFS-NOP-FINISHED "
+#define DFS_EVENT_PRE_CAC_EXPIRED "DFS-PRE-CAC-EXPIRED "
#define AP_CSA_FINISHED "AP-CSA-FINISHED "
@@ -282,12 +332,46 @@ extern "C" {
/* BSS Transition Management Response frame received */
#define BSS_TM_RESP "BSS-TM-RESP "
+/* Collocated Interference Request frame received;
+ * parameters: <dialog token> <automatic report enabled> <report timeout> */
+#define COLOC_INTF_REQ "COLOC-INTF-REQ "
+/* Collocated Interference Report frame received;
+ * parameters: <STA address> <dialog token> <hexdump of report elements> */
+#define COLOC_INTF_REPORT "COLOC-INTF-REPORT "
+
/* MBO IE with cellular data connection preference received */
#define MBO_CELL_PREFERENCE "MBO-CELL-PREFERENCE "
/* BSS Transition Management Request received with MBO transition reason */
#define MBO_TRANSITION_REASON "MBO-TRANSITION-REASON "
+/* parameters: <STA address> <dialog token> <ack=0/1> */
+#define BEACON_REQ_TX_STATUS "BEACON-REQ-TX-STATUS "
+/* parameters: <STA address> <dialog token> <report mode> <beacon report> */
+#define BEACON_RESP_RX "BEACON-RESP-RX "
+
+/* PMKSA cache entry added; parameters: <BSSID> <network_id> */
+#define PMKSA_CACHE_ADDED "PMKSA-CACHE-ADDED "
+/* PMKSA cache entry removed; parameters: <BSSID> <network_id> */
+#define PMKSA_CACHE_REMOVED "PMKSA-CACHE-REMOVED "
+
+/* FILS HLP Container receive; parameters: dst=<addr> src=<addr> frame=<hexdump>
+ */
+#define FILS_HLP_RX "FILS-HLP-RX "
+
+/* Event to indicate Probe Request frame;
+ * parameters: sa=<STA MAC address> signal=<signal> */
+#define RX_PROBE_REQUEST "RX-PROBE-REQUEST "
+
+/* Event to indicate station's HT/VHT operation mode change information */
+#define STA_OPMODE_MAX_BW_CHANGED "STA-OPMODE-MAX-BW-CHANGED "
+#define STA_OPMODE_SMPS_MODE_CHANGED "STA-OPMODE-SMPS-MODE-CHANGED "
+#define STA_OPMODE_N_SS_CHANGED "STA-OPMODE-N_SS-CHANGED "
+
+/* New interface addition or removal for 4addr WDS SDA */
+#define WDS_STA_INTERFACE_ADDED "WDS-STA-INTERFACE-ADDED "
+#define WDS_STA_INTERFACE_REMOVED "WDS-STA-INTERFACE-REMOVED "
+
/* BSS command information masks */
#define WPA_BSS_MASK_ALL 0xFFFDFFFF
@@ -313,6 +397,9 @@ extern "C" {
#define WPA_BSS_MASK_SNR BIT(19)
#define WPA_BSS_MASK_EST_THROUGHPUT BIT(20)
#define WPA_BSS_MASK_FST BIT(21)
+#define WPA_BSS_MASK_UPDATE_IDX BIT(22)
+#define WPA_BSS_MASK_BEACON_IE BIT(23)
+#define WPA_BSS_MASK_FILS_INDICATION BIT(24)
/* VENDOR_ELEM_* frame id values */
@@ -386,7 +473,7 @@ void wpa_ctrl_close(struct wpa_ctrl *ctrl);
*
* This function is used to send commands to wpa_supplicant/hostapd. Received
* response will be written to reply and reply_len is set to the actual length
- * of the reply. This function will block for up to two seconds while waiting
+ * of the reply. This function will block for up to 10 seconds while waiting
* for the reply. If unsolicited messages are received, the blocking time may
* be longer.
*
diff --git a/freebsd/contrib/wpa/src/crypto/aes-ctr.c b/freebsd/contrib/wpa/src/crypto/aes-ctr.c
index f92be022..0e6a3e21 100644
--- a/freebsd/contrib/wpa/src/crypto/aes-ctr.c
+++ b/freebsd/contrib/wpa/src/crypto/aes-ctr.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * AES-128 CTR
+ * AES-128/192/256 CTR
*
* Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
*
@@ -16,15 +16,16 @@
#include "aes_wrap.h"
/**
- * aes_128_ctr_encrypt - AES-128 CTR mode encryption
- * @key: Key for encryption (16 bytes)
+ * aes_ctr_encrypt - AES-128/192/256 CTR mode encryption
+ * @key: Key for encryption (key_len bytes)
+ * @key_len: Length of the key (16, 24, or 32 bytes)
* @nonce: Nonce for counter mode (16 bytes)
* @data: Data to encrypt in-place
* @data_len: Length of data in bytes
* Returns: 0 on success, -1 on failure
*/
-int aes_128_ctr_encrypt(const u8 *key, const u8 *nonce,
- u8 *data, size_t data_len)
+int aes_ctr_encrypt(const u8 *key, size_t key_len, const u8 *nonce,
+ u8 *data, size_t data_len)
{
void *ctx;
size_t j, len, left = data_len;
@@ -32,7 +33,7 @@ int aes_128_ctr_encrypt(const u8 *key, const u8 *nonce,
u8 *pos = data;
u8 counter[AES_BLOCK_SIZE], buf[AES_BLOCK_SIZE];
- ctx = aes_encrypt_init(key, 16);
+ ctx = aes_encrypt_init(key, key_len);
if (ctx == NULL)
return -1;
os_memcpy(counter, nonce, AES_BLOCK_SIZE);
@@ -55,3 +56,18 @@ int aes_128_ctr_encrypt(const u8 *key, const u8 *nonce,
aes_encrypt_deinit(ctx);
return 0;
}
+
+
+/**
+ * aes_128_ctr_encrypt - AES-128 CTR mode encryption
+ * @key: Key for encryption (key_len bytes)
+ * @nonce: Nonce for counter mode (16 bytes)
+ * @data: Data to encrypt in-place
+ * @data_len: Length of data in bytes
+ * Returns: 0 on success, -1 on failure
+ */
+int aes_128_ctr_encrypt(const u8 *key, const u8 *nonce,
+ u8 *data, size_t data_len)
+{
+ return aes_ctr_encrypt(key, 16, nonce, data, data_len);
+}
diff --git a/freebsd/contrib/wpa/src/crypto/aes.h b/freebsd/contrib/wpa/src/crypto/aes.h
index 2de59e04..8ab3de2e 100644
--- a/freebsd/contrib/wpa/src/crypto/aes.h
+++ b/freebsd/contrib/wpa/src/crypto/aes.h
@@ -12,10 +12,10 @@
#define AES_BLOCK_SIZE 16
void * aes_encrypt_init(const u8 *key, size_t len);
-void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt);
+int aes_encrypt(void *ctx, const u8 *plain, u8 *crypt);
void aes_encrypt_deinit(void *ctx);
void * aes_decrypt_init(const u8 *key, size_t len);
-void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain);
+int aes_decrypt(void *ctx, const u8 *crypt, u8 *plain);
void aes_decrypt_deinit(void *ctx);
#endif /* AES_H */
diff --git a/freebsd/contrib/wpa/src/crypto/aes_siv.h b/freebsd/contrib/wpa/src/crypto/aes_siv.h
new file mode 100644
index 00000000..fb05d80c
--- /dev/null
+++ b/freebsd/contrib/wpa/src/crypto/aes_siv.h
@@ -0,0 +1,21 @@
+/*
+ * AES SIV (RFC 5297)
+ * Copyright (c) 2013 Cozybit, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef AES_SIV_H
+#define AES_SIV_H
+
+int aes_siv_encrypt(const u8 *key, size_t key_len,
+ const u8 *pw, size_t pwlen,
+ size_t num_elem, const u8 *addr[], const size_t *len,
+ u8 *out);
+int aes_siv_decrypt(const u8 *key, size_t key_len,
+ const u8 *iv_crypt, size_t iv_c_len,
+ size_t num_elem, const u8 *addr[], const size_t *len,
+ u8 *out);
+
+#endif /* AES_SIV_H */
diff --git a/freebsd/contrib/wpa/src/crypto/aes_wrap.h b/freebsd/contrib/wpa/src/crypto/aes_wrap.h
index 4a142093..b70b1d26 100644
--- a/freebsd/contrib/wpa/src/crypto/aes_wrap.h
+++ b/freebsd/contrib/wpa/src/crypto/aes_wrap.h
@@ -3,7 +3,7 @@
*
* - AES Key Wrap Algorithm (RFC3394)
* - One-Key CBC MAC (OMAC1) hash with AES-128 and AES-256
- * - AES-128 CTR mode encryption
+ * - AES-128/192/256 CTR mode encryption
* - AES-128 EAX mode encryption/decryption
* - AES-128 CBC
* - AES-GCM
@@ -33,6 +33,8 @@ int __must_check omac1_aes_128(const u8 *key, const u8 *data, size_t data_len,
int __must_check omac1_aes_256(const u8 *key, const u8 *data, size_t data_len,
u8 *mac);
int __must_check aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out);
+int __must_check aes_ctr_encrypt(const u8 *key, size_t key_len, const u8 *nonce,
+ u8 *data, size_t data_len);
int __must_check aes_128_ctr_encrypt(const u8 *key, const u8 *nonce,
u8 *data, size_t data_len);
int __must_check aes_128_eax_encrypt(const u8 *key,
diff --git a/freebsd/contrib/wpa/src/crypto/crypto.h b/freebsd/contrib/wpa/src/crypto/crypto.h
index bdc3ba6f..12109ce8 100644
--- a/freebsd/contrib/wpa/src/crypto/crypto.h
+++ b/freebsd/contrib/wpa/src/crypto/crypto.h
@@ -1,6 +1,6 @@
/*
* Wrapper functions for crypto libraries
- * Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2017, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -106,8 +106,9 @@ int sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len,
* @clear: 8 octets (in)
* @key: 7 octets (in) (no parity bits included)
* @cypher: 8 octets (out)
+ * Returns: 0 on success, -1 on failure
*/
-void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher);
+int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher);
/**
* aes_encrypt_init - Initialize AES for encryption
@@ -122,8 +123,9 @@ void * aes_encrypt_init(const u8 *key, size_t len);
* @ctx: Context pointer from aes_encrypt_init()
* @plain: Plaintext data to be encrypted (16 bytes)
* @crypt: Buffer for the encrypted data (16 bytes)
+ * Returns: 0 on success, -1 on failure
*/
-void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt);
+int aes_encrypt(void *ctx, const u8 *plain, u8 *crypt);
/**
* aes_encrypt_deinit - Deinitialize AES encryption
@@ -144,8 +146,9 @@ void * aes_decrypt_init(const u8 *key, size_t len);
* @ctx: Context pointer from aes_encrypt_init()
* @crypt: Encrypted data (16 bytes)
* @plain: Buffer for the decrypted data (16 bytes)
+ * Returns: 0 on success, -1 on failure
*/
-void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain);
+int aes_decrypt(void *ctx, const u8 *crypt, u8 *plain);
/**
* aes_decrypt_deinit - Deinitialize AES decryption
@@ -414,6 +417,14 @@ int __must_check crypto_public_key_decrypt_pkcs1(
struct crypto_public_key *key, const u8 *crypt, size_t crypt_len,
u8 *plain, size_t *plain_len);
+int crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey,
+ u8 *pubkey);
+int crypto_dh_derive_secret(u8 generator, const u8 *prime, size_t prime_len,
+ const u8 *order, size_t order_len,
+ const u8 *privkey, size_t privkey_len,
+ const u8 *pubkey, size_t pubkey_len,
+ u8 *secret, size_t *len);
+
/**
* crypto_global_init - Initialize crypto wrapper
*
@@ -526,6 +537,14 @@ int crypto_bignum_to_bin(const struct crypto_bignum *a,
u8 *buf, size_t buflen, size_t padlen);
/**
+ * crypto_bignum_rand - Create a random number in range of modulus
+ * @r: Bignum; set to a random value
+ * @m: Bignum; modulus
+ * Returns: 0 on success, -1 on failure
+ */
+int crypto_bignum_rand(struct crypto_bignum *r, const struct crypto_bignum *m);
+
+/**
* crypto_bignum_add - c = a + b
* @a: Bignum
* @b: Bignum
@@ -607,6 +626,16 @@ int crypto_bignum_mulmod(const struct crypto_bignum *a,
struct crypto_bignum *d);
/**
+ * crypto_bignum_rshift - r = a >> n
+ * @a: Bignum
+ * @n: Number of bits
+ * @r: Bignum; used to store the result of a >> n
+ * Returns: 0 on success, -1 on failure
+ */
+int crypto_bignum_rshift(const struct crypto_bignum *a, int n,
+ struct crypto_bignum *r);
+
+/**
* crypto_bignum_cmp - Compare two bignums
* @a: Bignum
* @b: Bignum
@@ -637,6 +666,13 @@ int crypto_bignum_is_zero(const struct crypto_bignum *a);
int crypto_bignum_is_one(const struct crypto_bignum *a);
/**
+ * crypto_bignum_is_odd - Is the given bignum odd
+ * @a: Bignum
+ * Returns: 1 if @a is odd or 0 if not
+ */
+int crypto_bignum_is_odd(const struct crypto_bignum *a);
+
+/**
* crypto_bignum_legendre - Compute the Legendre symbol (a/p)
* @a: Bignum
* @p: Bignum
@@ -682,6 +718,13 @@ size_t crypto_ec_prime_len(struct crypto_ec *e);
size_t crypto_ec_prime_len_bits(struct crypto_ec *e);
/**
+ * crypto_ec_order_len - Get length of the order in octets
+ * @e: EC context from crypto_ec_init()
+ * Returns: Length of the order defining the group
+ */
+size_t crypto_ec_order_len(struct crypto_ec *e);
+
+/**
* crypto_ec_get_prime - Get prime defining an EC group
* @e: EC context from crypto_ec_init()
* Returns: Prime (bignum) defining the group
@@ -718,6 +761,16 @@ struct crypto_ec_point * crypto_ec_point_init(struct crypto_ec *e);
void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear);
/**
+ * crypto_ec_point_x - Copies the x-ordinate point into big number
+ * @e: EC context from crypto_ec_init()
+ * @p: EC point data
+ * @x: Big number to set to the copy of x-ordinate
+ * Returns: 0 on success, -1 on failure
+ */
+int crypto_ec_point_x(struct crypto_ec *e, const struct crypto_ec_point *p,
+ struct crypto_bignum *x);
+
+/**
* crypto_ec_point_to_bin - Write EC point value as binary data
* @e: EC context from crypto_ec_init()
* @p: EC point data from crypto_ec_point_init()
@@ -746,7 +799,7 @@ struct crypto_ec_point * crypto_ec_point_from_bin(struct crypto_ec *e,
const u8 *val);
/**
- * crypto_bignum_add - c = a + b
+ * crypto_ec_point_add - c = a + b
* @e: EC context from crypto_ec_init()
* @a: Bignum
* @b: Bignum
@@ -758,7 +811,7 @@ int crypto_ec_point_add(struct crypto_ec *e, const struct crypto_ec_point *a,
struct crypto_ec_point *c);
/**
- * crypto_bignum_mul - res = b * p
+ * crypto_ec_point_mul - res = b * p
* @e: EC context from crypto_ec_init()
* @p: EC point
* @b: Bignum
@@ -829,4 +882,12 @@ int crypto_ec_point_cmp(const struct crypto_ec *e,
const struct crypto_ec_point *a,
const struct crypto_ec_point *b);
+struct crypto_ecdh;
+
+struct crypto_ecdh * crypto_ecdh_init(int group);
+struct wpabuf * crypto_ecdh_get_pubkey(struct crypto_ecdh *ecdh, int inc_y);
+struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y,
+ const u8 *key, size_t len);
+void crypto_ecdh_deinit(struct crypto_ecdh *ecdh);
+
#endif /* CRYPTO_H */
diff --git a/freebsd/contrib/wpa/src/crypto/crypto_openssl.c b/freebsd/contrib/wpa/src/crypto/crypto_openssl.c
index ee4d55eb..5b4c41a9 100644
--- a/freebsd/contrib/wpa/src/crypto/crypto_openssl.c
+++ b/freebsd/contrib/wpa/src/crypto/crypto_openssl.c
@@ -2,7 +2,7 @@
/*
* Wrapper functions for OpenSSL libcrypto
- * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2017, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -26,16 +26,20 @@
#endif /* CONFIG_ECC */
#include "common.h"
+#include "utils/const_time.h"
#include "wpabuf.h"
#include "dh_group5.h"
#include "sha1.h"
#include "sha256.h"
#include "sha384.h"
+#include "sha512.h"
#include "md5.h"
#include "aes_wrap.h"
#include "crypto.h"
-#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
+ (defined(LIBRESSL_VERSION_NUMBER) && \
+ LIBRESSL_VERSION_NUMBER < 0x20700000L)
/* Compatibility wrappers for older versions. */
static HMAC_CTX * HMAC_CTX_new(void)
@@ -81,7 +85,9 @@ static void EVP_MD_CTX_free(EVP_MD_CTX *ctx)
static BIGNUM * get_group5_prime(void)
{
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
+ !(defined(LIBRESSL_VERSION_NUMBER) && \
+ LIBRESSL_VERSION_NUMBER < 0x20700000L)
return BN_get_rfc3526_prime_1536(NULL);
#elif !defined(OPENSSL_IS_BORINGSSL)
return get_rfc3526_prime_1536(NULL);
@@ -108,9 +114,37 @@ static BIGNUM * get_group5_prime(void)
#endif
}
+
+static BIGNUM * get_group5_order(void)
+{
+ static const unsigned char RFC3526_ORDER_1536[] = {
+ 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE4,0x87,0xED,0x51,
+ 0x10,0xB4,0x61,0x1A,0x62,0x63,0x31,0x45,0xC0,0x6E,0x0E,0x68,
+ 0x94,0x81,0x27,0x04,0x45,0x33,0xE6,0x3A,0x01,0x05,0xDF,0x53,
+ 0x1D,0x89,0xCD,0x91,0x28,0xA5,0x04,0x3C,0xC7,0x1A,0x02,0x6E,
+ 0xF7,0xCA,0x8C,0xD9,0xE6,0x9D,0x21,0x8D,0x98,0x15,0x85,0x36,
+ 0xF9,0x2F,0x8A,0x1B,0xA7,0xF0,0x9A,0xB6,0xB6,0xA8,0xE1,0x22,
+ 0xF2,0x42,0xDA,0xBB,0x31,0x2F,0x3F,0x63,0x7A,0x26,0x21,0x74,
+ 0xD3,0x1B,0xF6,0xB5,0x85,0xFF,0xAE,0x5B,0x7A,0x03,0x5B,0xF6,
+ 0xF7,0x1C,0x35,0xFD,0xAD,0x44,0xCF,0xD2,0xD7,0x4F,0x92,0x08,
+ 0xBE,0x25,0x8F,0xF3,0x24,0x94,0x33,0x28,0xF6,0x72,0x2D,0x9E,
+ 0xE1,0x00,0x3E,0x5C,0x50,0xB1,0xDF,0x82,0xCC,0x6D,0x24,0x1B,
+ 0x0E,0x2A,0xE9,0xCD,0x34,0x8B,0x1F,0xD4,0x7E,0x92,0x67,0xAF,
+ 0xC1,0xB2,0xAE,0x91,0xEE,0x51,0xD6,0xCB,0x0E,0x31,0x79,0xAB,
+ 0x10,0x42,0xA9,0x5D,0xCF,0x6A,0x94,0x83,0xB8,0x4B,0x4B,0x36,
+ 0xB3,0x86,0x1A,0xA7,0x25,0x5E,0x4C,0x02,0x78,0xBA,0x36,0x04,
+ 0x65,0x11,0xB9,0x93,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+ };
+ return BN_bin2bn(RFC3526_ORDER_1536, sizeof(RFC3526_ORDER_1536), NULL);
+}
+
+
#ifdef OPENSSL_NO_SHA256
#define NO_SHA256_WRAPPER
#endif
+#ifdef OPENSSL_NO_SHA512
+#define NO_SHA384_WRAPPER
+#endif
static int openssl_digest_vector(const EVP_MD *type, size_t num_elem,
const u8 *addr[], const size_t *len, u8 *mac)
@@ -160,7 +194,7 @@ int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
#endif /* CONFIG_FIPS */
-void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
+int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
{
u8 pkey[8], next, tmp;
int i;
@@ -178,6 +212,7 @@ void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
DES_set_key((DES_cblock *) &pkey, &ks);
DES_ecb_encrypt((DES_cblock *) clear, (DES_cblock *) cypher, &ks,
DES_ENCRYPT);
+ return 0;
}
@@ -245,15 +280,31 @@ int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
#endif /* NO_SHA256_WRAPPER */
+#ifndef NO_SHA384_WRAPPER
+int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len,
+ u8 *mac)
+{
+ return openssl_digest_vector(EVP_sha384(), num_elem, addr, len, mac);
+}
+#endif /* NO_SHA384_WRAPPER */
+
+
+#ifndef NO_SHA512_WRAPPER
+int sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len,
+ u8 *mac)
+{
+ return openssl_digest_vector(EVP_sha512(), num_elem, addr, len, mac);
+}
+#endif /* NO_SHA512_WRAPPER */
+
+
static const EVP_CIPHER * aes_get_evp_cipher(size_t keylen)
{
switch (keylen) {
case 16:
return EVP_aes_128_ecb();
-#ifndef OPENSSL_IS_BORINGSSL
case 24:
return EVP_aes_192_ecb();
-#endif /* OPENSSL_IS_BORINGSSL */
case 32:
return EVP_aes_256_ecb();
}
@@ -271,8 +322,11 @@ void * aes_encrypt_init(const u8 *key, size_t len)
return NULL;
type = aes_get_evp_cipher(len);
- if (type == NULL)
+ if (!type) {
+ wpa_printf(MSG_INFO, "%s: Unsupported len=%u",
+ __func__, (unsigned int) len);
return NULL;
+ }
ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL)
@@ -286,14 +340,16 @@ void * aes_encrypt_init(const u8 *key, size_t len)
}
-void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
+int aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
{
EVP_CIPHER_CTX *c = ctx;
int clen = 16;
if (EVP_EncryptUpdate(c, crypt, &clen, plain, 16) != 1) {
wpa_printf(MSG_ERROR, "OpenSSL: EVP_EncryptUpdate failed: %s",
ERR_error_string(ERR_get_error(), NULL));
+ return -1;
}
+ return 0;
}
@@ -323,8 +379,11 @@ void * aes_decrypt_init(const u8 *key, size_t len)
return NULL;
type = aes_get_evp_cipher(len);
- if (type == NULL)
+ if (!type) {
+ wpa_printf(MSG_INFO, "%s: Unsupported len=%u",
+ __func__, (unsigned int) len);
return NULL;
+ }
ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL)
@@ -338,14 +397,16 @@ void * aes_decrypt_init(const u8 *key, size_t len)
}
-void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
+int aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
{
EVP_CIPHER_CTX *c = ctx;
int plen = 16;
if (EVP_DecryptUpdate(c, plain, &plen, crypt, 16) != 1) {
wpa_printf(MSG_ERROR, "OpenSSL: EVP_DecryptUpdate failed: %s",
ERR_error_string(ERR_get_error(), NULL));
+ return -1;
}
+ return 0;
}
@@ -374,6 +435,8 @@ int aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain, u8 *cipher)
AES_KEY actx;
int res;
+ if (TEST_FAIL())
+ return -1;
if (AES_set_encrypt_key(kek, kek_len << 3, &actx))
return -1;
res = AES_wrap_key(&actx, NULL, cipher, plain, n * 8);
@@ -388,6 +451,8 @@ int aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher,
AES_KEY actx;
int res;
+ if (TEST_FAIL())
+ return -1;
if (AES_set_decrypt_key(kek, kek_len << 3, &actx))
return -1;
res = AES_unwrap_key(&actx, NULL, plain, cipher, (n + 1) * 8);
@@ -454,6 +519,75 @@ int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
}
+int crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey,
+ u8 *pubkey)
+{
+ size_t pubkey_len, pad;
+
+ if (os_get_random(privkey, prime_len) < 0)
+ return -1;
+ if (os_memcmp(privkey, prime, prime_len) > 0) {
+ /* Make sure private value is smaller than prime */
+ privkey[0] = 0;
+ }
+
+ pubkey_len = prime_len;
+ if (crypto_mod_exp(&generator, 1, privkey, prime_len, prime, prime_len,
+ pubkey, &pubkey_len) < 0)
+ return -1;
+ if (pubkey_len < prime_len) {
+ pad = prime_len - pubkey_len;
+ os_memmove(pubkey + pad, pubkey, pubkey_len);
+ os_memset(pubkey, 0, pad);
+ }
+
+ return 0;
+}
+
+
+int crypto_dh_derive_secret(u8 generator, const u8 *prime, size_t prime_len,
+ const u8 *order, size_t order_len,
+ const u8 *privkey, size_t privkey_len,
+ const u8 *pubkey, size_t pubkey_len,
+ u8 *secret, size_t *len)
+{
+ BIGNUM *pub, *p;
+ int res = -1;
+
+ pub = BN_bin2bn(pubkey, pubkey_len, NULL);
+ p = BN_bin2bn(prime, prime_len, NULL);
+ if (!pub || !p || BN_is_zero(pub) || BN_is_one(pub) ||
+ BN_cmp(pub, p) >= 0)
+ goto fail;
+
+ if (order) {
+ BN_CTX *ctx;
+ BIGNUM *q, *tmp;
+ int failed;
+
+ /* verify: pubkey^q == 1 mod p */
+ q = BN_bin2bn(order, order_len, NULL);
+ ctx = BN_CTX_new();
+ tmp = BN_new();
+ failed = !q || !ctx || !tmp ||
+ !BN_mod_exp(tmp, pub, q, p, ctx) ||
+ !BN_is_one(tmp);
+ BN_clear(q);
+ BN_clear(tmp);
+ BN_CTX_free(ctx);
+ if (failed)
+ goto fail;
+ }
+
+ res = crypto_mod_exp(pubkey, pubkey_len, privkey, privkey_len,
+ prime, prime_len, secret, len);
+fail:
+ BN_clear(pub);
+ BN_clear(p);
+ return res;
+}
+
+
int crypto_mod_exp(const u8 *base, size_t base_len,
const u8 *power, size_t power_len,
const u8 *modulus, size_t modulus_len,
@@ -476,7 +610,8 @@ int crypto_mod_exp(const u8 *base, size_t base_len,
bn_result == NULL)
goto error;
- if (BN_mod_exp(bn_result, bn_base, bn_exp, bn_modulus, ctx) != 1)
+ if (BN_mod_exp_mont_consttime(bn_result, bn_base, bn_exp, bn_modulus,
+ ctx, NULL) != 1)
goto error;
*result_len = BN_bn2bin(bn_result, result);
@@ -613,7 +748,9 @@ void crypto_cipher_deinit(struct crypto_cipher *ctx)
void * dh5_init(struct wpabuf **priv, struct wpabuf **publ)
{
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
+ (defined(LIBRESSL_VERSION_NUMBER) && \
+ LIBRESSL_VERSION_NUMBER < 0x20700000L)
DH *dh;
struct wpabuf *pubkey = NULL, *privkey = NULL;
size_t publen, privlen;
@@ -634,6 +771,10 @@ void * dh5_init(struct wpabuf **priv, struct wpabuf **publ)
if (dh->p == NULL)
goto err;
+ dh->q = get_group5_order();
+ if (!dh->q)
+ goto err;
+
if (DH_generate_key(dh) != 1)
goto err;
@@ -662,7 +803,7 @@ err:
DH *dh;
struct wpabuf *pubkey = NULL, *privkey = NULL;
size_t publen, privlen;
- BIGNUM *p = NULL, *g;
+ BIGNUM *p, *g, *q;
const BIGNUM *priv_key = NULL, *pub_key = NULL;
*priv = NULL;
@@ -675,10 +816,12 @@ err:
g = BN_new();
p = get_group5_prime();
- if (!g || BN_set_word(g, 2) != 1 || !p ||
- DH_set0_pqg(dh, p, NULL, g) != 1)
+ q = get_group5_order();
+ if (!g || BN_set_word(g, 2) != 1 || !p || !q ||
+ DH_set0_pqg(dh, p, q, g) != 1)
goto err;
p = NULL;
+ q = NULL;
g = NULL;
if (DH_generate_key(dh) != 1)
@@ -703,6 +846,7 @@ err:
err:
BN_free(p);
+ BN_free(q);
BN_free(g);
wpabuf_clear_free(pubkey);
wpabuf_clear_free(privkey);
@@ -714,7 +858,9 @@ err:
void * dh5_init_fixed(const struct wpabuf *priv, const struct wpabuf *publ)
{
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
+ (defined(LIBRESSL_VERSION_NUMBER) && \
+ LIBRESSL_VERSION_NUMBER < 0x20700000L)
DH *dh;
dh = DH_new();
@@ -910,6 +1056,9 @@ int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
HMAC_CTX_free(ctx->ctx);
bin_clear_free(ctx, sizeof(*ctx));
+ if (TEST_FAIL())
+ return -1;
+
if (res == 1) {
*len = mdlen;
return 0;
@@ -1018,7 +1167,7 @@ int hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem,
const u8 *addr[], const size_t *len, u8 *mac)
{
return openssl_hmac_vector(EVP_sha384(), key, key_len, num_elem, addr,
- len, mac, 32);
+ len, mac, 48);
}
@@ -1031,6 +1180,25 @@ int hmac_sha384(const u8 *key, size_t key_len, const u8 *data,
#endif /* CONFIG_SHA384 */
+#ifdef CONFIG_SHA512
+
+int hmac_sha512_vector(const u8 *key, size_t key_len, size_t num_elem,
+ const u8 *addr[], const size_t *len, u8 *mac)
+{
+ return openssl_hmac_vector(EVP_sha512(), key, key_len, num_elem, addr,
+ len, mac, 64);
+}
+
+
+int hmac_sha512(const u8 *key, size_t key_len, const u8 *data,
+ size_t data_len, u8 *mac)
+{
+ return hmac_sha512_vector(key, key_len, 1, &data, &data_len, mac);
+}
+
+#endif /* CONFIG_SHA512 */
+
+
int crypto_get_random(void *buf, size_t len)
{
if (RAND_bytes(buf, len) != 1)
@@ -1152,6 +1320,14 @@ int crypto_bignum_to_bin(const struct crypto_bignum *a,
}
+int crypto_bignum_rand(struct crypto_bignum *r, const struct crypto_bignum *m)
+{
+ if (TEST_FAIL())
+ return -1;
+ return BN_rand_range((BIGNUM *) r, (const BIGNUM *) m) == 1 ? 0 : -1;
+}
+
+
int crypto_bignum_add(const struct crypto_bignum *a,
const struct crypto_bignum *b,
struct crypto_bignum *c)
@@ -1193,8 +1369,9 @@ int crypto_bignum_exptmod(const struct crypto_bignum *a,
bnctx = BN_CTX_new();
if (bnctx == NULL)
return -1;
- res = BN_mod_exp((BIGNUM *) d, (const BIGNUM *) a, (const BIGNUM *) b,
- (const BIGNUM *) c, bnctx);
+ res = BN_mod_exp_mont_consttime((BIGNUM *) d, (const BIGNUM *) a,
+ (const BIGNUM *) b, (const BIGNUM *) c,
+ bnctx, NULL);
BN_CTX_free(bnctx);
return res ? 0 : -1;
@@ -1213,6 +1390,11 @@ int crypto_bignum_inverse(const struct crypto_bignum *a,
bnctx = BN_CTX_new();
if (bnctx == NULL)
return -1;
+#ifdef OPENSSL_IS_BORINGSSL
+ /* TODO: use BN_mod_inverse_blinded() ? */
+#else /* OPENSSL_IS_BORINGSSL */
+ BN_set_flags((BIGNUM *) a, BN_FLG_CONSTTIME);
+#endif /* OPENSSL_IS_BORINGSSL */
res = BN_mod_inverse((BIGNUM *) c, (const BIGNUM *) a,
(const BIGNUM *) b, bnctx);
BN_CTX_free(bnctx);
@@ -1246,6 +1428,9 @@ int crypto_bignum_div(const struct crypto_bignum *a,
bnctx = BN_CTX_new();
if (bnctx == NULL)
return -1;
+#ifndef OPENSSL_IS_BORINGSSL
+ BN_set_flags((BIGNUM *) a, BN_FLG_CONSTTIME);
+#endif /* OPENSSL_IS_BORINGSSL */
res = BN_div((BIGNUM *) c, NULL, (const BIGNUM *) a,
(const BIGNUM *) b, bnctx);
BN_CTX_free(bnctx);
@@ -1277,6 +1462,15 @@ int crypto_bignum_mulmod(const struct crypto_bignum *a,
}
+int crypto_bignum_rshift(const struct crypto_bignum *a, int n,
+ struct crypto_bignum *r)
+{
+ /* Note: BN_rshift() does not modify the first argument even though it
+ * has not been marked const. */
+ return BN_rshift((BIGNUM *) a, (BIGNUM *) r, n) == 1 ? 0 : -1;
+}
+
+
int crypto_bignum_cmp(const struct crypto_bignum *a,
const struct crypto_bignum *b)
{
@@ -1302,12 +1496,19 @@ int crypto_bignum_is_one(const struct crypto_bignum *a)
}
+int crypto_bignum_is_odd(const struct crypto_bignum *a)
+{
+ return BN_is_odd((const BIGNUM *) a);
+}
+
+
int crypto_bignum_legendre(const struct crypto_bignum *a,
const struct crypto_bignum *p)
{
BN_CTX *bnctx;
BIGNUM *exp = NULL, *tmp = NULL;
int res = -2;
+ unsigned int mask;
if (TEST_FAIL())
return -2;
@@ -1322,16 +1523,17 @@ int crypto_bignum_legendre(const struct crypto_bignum *a,
/* exp = (p-1) / 2 */
!BN_sub(exp, (const BIGNUM *) p, BN_value_one()) ||
!BN_rshift1(exp, exp) ||
- !BN_mod_exp(tmp, (const BIGNUM *) a, exp, (const BIGNUM *) p,
- bnctx))
+ !BN_mod_exp_mont_consttime(tmp, (const BIGNUM *) a, exp,
+ (const BIGNUM *) p, bnctx, NULL))
goto fail;
- if (BN_is_word(tmp, 1))
- res = 1;
- else if (BN_is_zero(tmp))
- res = 0;
- else
- res = -1;
+ /* Return 1 if tmp == 1, 0 if tmp == 0, or -1 otherwise. Need to use
+ * constant time selection to avoid branches here. */
+ res = -1;
+ mask = const_time_eq(BN_is_word(tmp, 1), 1);
+ res = const_time_select_int(mask, 1, res);
+ mask = const_time_eq(BN_is_zero(tmp), 1);
+ res = const_time_select_int(mask, 0, res);
fail:
BN_clear_free(tmp);
@@ -1345,6 +1547,7 @@ fail:
struct crypto_ec {
EC_GROUP *group;
+ int nid;
BN_CTX *bnctx;
BIGNUM *prime;
BIGNUM *order;
@@ -1402,6 +1605,7 @@ struct crypto_ec * crypto_ec_init(int group)
if (e == NULL)
return NULL;
+ e->nid = nid;
e->bnctx = BN_CTX_new();
e->group = EC_GROUP_new_by_curve_name(nid);
e->prime = BN_new();
@@ -1456,6 +1660,12 @@ size_t crypto_ec_prime_len_bits(struct crypto_ec *e)
}
+size_t crypto_ec_order_len(struct crypto_ec *e)
+{
+ return BN_num_bytes(e->order);
+}
+
+
const struct crypto_bignum * crypto_ec_get_prime(struct crypto_ec *e)
{
return (const struct crypto_bignum *) e->prime;
@@ -1477,6 +1687,16 @@ void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear)
}
+int crypto_ec_point_x(struct crypto_ec *e, const struct crypto_ec_point *p,
+ struct crypto_bignum *x)
+{
+ return EC_POINT_get_affine_coordinates_GFp(e->group,
+ (const EC_POINT *) p,
+ (BIGNUM *) x, NULL,
+ e->bnctx) == 1 ? 0 : -1;
+}
+
+
int crypto_ec_point_to_bin(struct crypto_ec *e,
const struct crypto_ec_point *point, u8 *x, u8 *y)
{
@@ -1642,4 +1862,228 @@ int crypto_ec_point_cmp(const struct crypto_ec *e,
(const EC_POINT *) b, e->bnctx);
}
+
+struct crypto_ecdh {
+ struct crypto_ec *ec;
+ EVP_PKEY *pkey;
+};
+
+struct crypto_ecdh * crypto_ecdh_init(int group)
+{
+ struct crypto_ecdh *ecdh;
+ EVP_PKEY *params = NULL;
+ EC_KEY *ec_params;
+ EVP_PKEY_CTX *kctx = NULL;
+
+ ecdh = os_zalloc(sizeof(*ecdh));
+ if (!ecdh)
+ goto fail;
+
+ ecdh->ec = crypto_ec_init(group);
+ if (!ecdh->ec)
+ goto fail;
+
+ ec_params = EC_KEY_new_by_curve_name(ecdh->ec->nid);
+ if (!ec_params) {
+ wpa_printf(MSG_ERROR,
+ "OpenSSL: Failed to generate EC_KEY parameters");
+ goto fail;
+ }
+ EC_KEY_set_asn1_flag(ec_params, OPENSSL_EC_NAMED_CURVE);
+ params = EVP_PKEY_new();
+ if (!params || EVP_PKEY_set1_EC_KEY(params, ec_params) != 1) {
+ wpa_printf(MSG_ERROR,
+ "OpenSSL: Failed to generate EVP_PKEY parameters");
+ goto fail;
+ }
+
+ kctx = EVP_PKEY_CTX_new(params, NULL);
+ if (!kctx)
+ goto fail;
+
+ if (EVP_PKEY_keygen_init(kctx) != 1) {
+ wpa_printf(MSG_ERROR,
+ "OpenSSL: EVP_PKEY_keygen_init failed: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ goto fail;
+ }
+
+ if (EVP_PKEY_keygen(kctx, &ecdh->pkey) != 1) {
+ wpa_printf(MSG_ERROR, "OpenSSL: EVP_PKEY_keygen failed: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ goto fail;
+ }
+
+done:
+ EVP_PKEY_free(params);
+ EVP_PKEY_CTX_free(kctx);
+
+ return ecdh;
+fail:
+ crypto_ecdh_deinit(ecdh);
+ ecdh = NULL;
+ goto done;
+}
+
+
+struct wpabuf * crypto_ecdh_get_pubkey(struct crypto_ecdh *ecdh, int inc_y)
+{
+ struct wpabuf *buf = NULL;
+ EC_KEY *eckey;
+ const EC_POINT *pubkey;
+ BIGNUM *x, *y = NULL;
+ int len = BN_num_bytes(ecdh->ec->prime);
+ int res;
+
+ eckey = EVP_PKEY_get1_EC_KEY(ecdh->pkey);
+ if (!eckey)
+ return NULL;
+
+ pubkey = EC_KEY_get0_public_key(eckey);
+ if (!pubkey)
+ return NULL;
+
+ x = BN_new();
+ if (inc_y) {
+ y = BN_new();
+ if (!y)
+ goto fail;
+ }
+ buf = wpabuf_alloc(inc_y ? 2 * len : len);
+ if (!x || !buf)
+ goto fail;
+
+ if (EC_POINT_get_affine_coordinates_GFp(ecdh->ec->group, pubkey,
+ x, y, ecdh->ec->bnctx) != 1) {
+ wpa_printf(MSG_ERROR,
+ "OpenSSL: EC_POINT_get_affine_coordinates_GFp failed: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ goto fail;
+ }
+
+ res = crypto_bignum_to_bin((struct crypto_bignum *) x,
+ wpabuf_put(buf, len), len, len);
+ if (res < 0)
+ goto fail;
+
+ if (inc_y) {
+ res = crypto_bignum_to_bin((struct crypto_bignum *) y,
+ wpabuf_put(buf, len), len, len);
+ if (res < 0)
+ goto fail;
+ }
+
+done:
+ BN_clear_free(x);
+ BN_clear_free(y);
+ EC_KEY_free(eckey);
+
+ return buf;
+fail:
+ wpabuf_free(buf);
+ buf = NULL;
+ goto done;
+}
+
+
+struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y,
+ const u8 *key, size_t len)
+{
+ BIGNUM *x, *y = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
+ EVP_PKEY *peerkey = NULL;
+ struct wpabuf *secret = NULL;
+ size_t secret_len;
+ EC_POINT *pub;
+ EC_KEY *eckey = NULL;
+
+ x = BN_bin2bn(key, inc_y ? len / 2 : len, NULL);
+ pub = EC_POINT_new(ecdh->ec->group);
+ if (!x || !pub)
+ goto fail;
+
+ if (inc_y) {
+ y = BN_bin2bn(key + len / 2, len / 2, NULL);
+ if (!y)
+ goto fail;
+ if (!EC_POINT_set_affine_coordinates_GFp(ecdh->ec->group, pub,
+ x, y,
+ ecdh->ec->bnctx)) {
+ wpa_printf(MSG_ERROR,
+ "OpenSSL: EC_POINT_set_affine_coordinates_GFp failed: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ goto fail;
+ }
+ } else if (!EC_POINT_set_compressed_coordinates_GFp(ecdh->ec->group,
+ pub, x, 0,
+ ecdh->ec->bnctx)) {
+ wpa_printf(MSG_ERROR,
+ "OpenSSL: EC_POINT_set_compressed_coordinates_GFp failed: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ goto fail;
+ }
+
+ if (!EC_POINT_is_on_curve(ecdh->ec->group, pub, ecdh->ec->bnctx)) {
+ wpa_printf(MSG_ERROR,
+ "OpenSSL: ECDH peer public key is not on curve");
+ goto fail;
+ }
+
+ eckey = EC_KEY_new_by_curve_name(ecdh->ec->nid);
+ if (!eckey || EC_KEY_set_public_key(eckey, pub) != 1) {
+ wpa_printf(MSG_ERROR,
+ "OpenSSL: EC_KEY_set_public_key failed: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ goto fail;
+ }
+
+ peerkey = EVP_PKEY_new();
+ if (!peerkey || EVP_PKEY_set1_EC_KEY(peerkey, eckey) != 1)
+ goto fail;
+
+ ctx = EVP_PKEY_CTX_new(ecdh->pkey, NULL);
+ if (!ctx || EVP_PKEY_derive_init(ctx) != 1 ||
+ EVP_PKEY_derive_set_peer(ctx, peerkey) != 1 ||
+ EVP_PKEY_derive(ctx, NULL, &secret_len) != 1) {
+ wpa_printf(MSG_ERROR,
+ "OpenSSL: EVP_PKEY_derive(1) failed: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ goto fail;
+ }
+
+ secret = wpabuf_alloc(secret_len);
+ if (!secret)
+ goto fail;
+ if (EVP_PKEY_derive(ctx, wpabuf_put(secret, secret_len),
+ &secret_len) != 1) {
+ wpa_printf(MSG_ERROR,
+ "OpenSSL: EVP_PKEY_derive(2) failed: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ goto fail;
+ }
+
+done:
+ BN_free(x);
+ BN_free(y);
+ EC_KEY_free(eckey);
+ EC_POINT_free(pub);
+ EVP_PKEY_CTX_free(ctx);
+ EVP_PKEY_free(peerkey);
+ return secret;
+fail:
+ wpabuf_free(secret);
+ secret = NULL;
+ goto done;
+}
+
+
+void crypto_ecdh_deinit(struct crypto_ecdh *ecdh)
+{
+ if (ecdh) {
+ crypto_ec_deinit(ecdh->ec);
+ EVP_PKEY_free(ecdh->pkey);
+ os_free(ecdh);
+ }
+}
+
#endif /* CONFIG_ECC */
diff --git a/freebsd/contrib/wpa/src/crypto/ms_funcs.c b/freebsd/contrib/wpa/src/crypto/ms_funcs.c
index 67e98dbf..a89a8fda 100644
--- a/freebsd/contrib/wpa/src/crypto/ms_funcs.c
+++ b/freebsd/contrib/wpa/src/crypto/ms_funcs.c
@@ -142,17 +142,20 @@ int hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash)
* @challenge: 8-octet Challenge (IN)
* @password_hash: 16-octet PasswordHash (IN)
* @response: 24-octet Response (OUT)
+ * Returns: 0 on success, -1 on failure
*/
-void challenge_response(const u8 *challenge, const u8 *password_hash,
- u8 *response)
+int challenge_response(const u8 *challenge, const u8 *password_hash,
+ u8 *response)
{
u8 zpwd[7];
- des_encrypt(challenge, password_hash, response);
- des_encrypt(challenge, password_hash + 7, response + 8);
+
+ if (des_encrypt(challenge, password_hash, response) < 0 ||
+ des_encrypt(challenge, password_hash + 7, response + 8) < 0)
+ return -1;
zpwd[0] = password_hash[14];
zpwd[1] = password_hash[15];
os_memset(zpwd + 2, 0, 5);
- des_encrypt(challenge, zpwd, response + 16);
+ return des_encrypt(challenge, zpwd, response + 16);
}
@@ -177,9 +180,9 @@ int generate_nt_response(const u8 *auth_challenge, const u8 *peer_challenge,
if (challenge_hash(peer_challenge, auth_challenge, username,
username_len, challenge) ||
- nt_password_hash(password, password_len, password_hash))
+ nt_password_hash(password, password_len, password_hash) ||
+ challenge_response(challenge, password_hash, response))
return -1;
- challenge_response(challenge, password_hash, response);
return 0;
}
@@ -204,9 +207,9 @@ int generate_nt_response_pwhash(const u8 *auth_challenge,
if (challenge_hash(peer_challenge, auth_challenge,
username, username_len,
- challenge))
+ challenge) ||
+ challenge_response(challenge, password_hash, response))
return -1;
- challenge_response(challenge, password_hash, response);
return 0;
}
@@ -306,9 +309,10 @@ int nt_challenge_response(const u8 *challenge, const u8 *password,
size_t password_len, u8 *response)
{
u8 password_hash[16];
- if (nt_password_hash(password, password_len, password_hash))
+
+ if (nt_password_hash(password, password_len, password_hash) ||
+ challenge_response(challenge, password_hash, response))
return -1;
- challenge_response(challenge, password_hash, response);
return 0;
}
@@ -489,12 +493,15 @@ int new_password_encrypted_with_old_nt_password_hash(
* @password_hash: 16-octer PasswordHash (IN)
* @block: 16-octet Block (IN)
* @cypher: 16-octer Cypher (OUT)
+ * Returns: 0 on success, -1 on failure
*/
-void nt_password_hash_encrypted_with_block(const u8 *password_hash,
- const u8 *block, u8 *cypher)
+int nt_password_hash_encrypted_with_block(const u8 *password_hash,
+ const u8 *block, u8 *cypher)
{
- des_encrypt(password_hash, block, cypher);
- des_encrypt(password_hash + 8, block + 7, cypher + 8);
+ if (des_encrypt(password_hash, block, cypher) < 0 ||
+ des_encrypt(password_hash + 8, block + 7, cypher + 8) < 0)
+ return -1;
+ return 0;
}
@@ -517,10 +524,10 @@ int old_nt_password_hash_encrypted_with_new_nt_password_hash(
if (nt_password_hash(old_password, old_password_len,
old_password_hash) ||
nt_password_hash(new_password, new_password_len,
- new_password_hash))
+ new_password_hash) ||
+ nt_password_hash_encrypted_with_block(old_password_hash,
+ new_password_hash,
+ encrypted_password_hash))
return -1;
- nt_password_hash_encrypted_with_block(old_password_hash,
- new_password_hash,
- encrypted_password_hash);
return 0;
}
diff --git a/freebsd/contrib/wpa/src/crypto/ms_funcs.h b/freebsd/contrib/wpa/src/crypto/ms_funcs.h
index b5b5918e..b8d55f05 100644
--- a/freebsd/contrib/wpa/src/crypto/ms_funcs.h
+++ b/freebsd/contrib/wpa/src/crypto/ms_funcs.h
@@ -31,8 +31,8 @@ int generate_authenticator_response_pwhash(
int nt_challenge_response(const u8 *challenge, const u8 *password,
size_t password_len, u8 *response);
-void challenge_response(const u8 *challenge, const u8 *password_hash,
- u8 *response);
+int challenge_response(const u8 *challenge, const u8 *password_hash,
+ u8 *response);
int challenge_hash(const u8 *peer_challenge, const u8 *auth_challenge,
const u8 *username, size_t username_len, u8 *challenge);
int nt_password_hash(const u8 *password, size_t password_len,
@@ -50,8 +50,8 @@ int __must_check new_password_encrypted_with_old_nt_password_hash(
const u8 *new_password, size_t new_password_len,
const u8 *old_password, size_t old_password_len,
u8 *encrypted_pw_block);
-void nt_password_hash_encrypted_with_block(const u8 *password_hash,
- const u8 *block, u8 *cypher);
+int nt_password_hash_encrypted_with_block(const u8 *password_hash,
+ const u8 *block, u8 *cypher);
int old_nt_password_hash_encrypted_with_new_nt_password_hash(
const u8 *new_password, size_t new_password_len,
const u8 *old_password, size_t old_password_len,
diff --git a/freebsd/contrib/wpa/src/crypto/random.c b/freebsd/contrib/wpa/src/crypto/random.c
index 57880e31..8fd57a57 100644
--- a/freebsd/contrib/wpa/src/crypto/random.c
+++ b/freebsd/contrib/wpa/src/crypto/random.c
@@ -27,6 +27,9 @@
#include "utils/includes.h"
#ifdef __linux__
#include <fcntl.h>
+#ifdef CONFIG_GETRANDOM
+#include <sys/random.h>
+#endif /* CONFIG_GETRANDOM */
#endif /* __linux__ */
#include "utils/common.h"
@@ -56,7 +59,6 @@ static int random_fd = -1;
static unsigned int own_pool_ready = 0;
#define RANDOM_ENTROPY_SIZE 20
static char *random_entropy_file = NULL;
-static int random_entropy_file_read = 0;
#define MIN_COLLECT_ENTROPY 1000
static unsigned int entropy = 0;
@@ -68,6 +70,9 @@ static void random_write_entropy(void);
static u32 __ROL32(u32 x, u32 y)
{
+ if (y == 0)
+ return x;
+
return (x << (y & 31)) | (x >> (32 - (y & 31)));
}
@@ -228,30 +233,52 @@ int random_pool_ready(void)
return 1; /* Already initialized - good to continue */
/*
- * Try to fetch some more data from the kernel high quality
- * /dev/random. There may not be enough data available at this point,
+ * Try to fetch some more data from the kernel high quality RNG.
+ * There may not be enough data available at this point,
* so use non-blocking read to avoid blocking the application
* completely.
*/
- fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
- if (fd < 0) {
- wpa_printf(MSG_ERROR, "random: Cannot open /dev/random: %s",
- strerror(errno));
- return -1;
- }
- res = read(fd, dummy_key + dummy_key_avail,
- sizeof(dummy_key) - dummy_key_avail);
+#ifdef CONFIG_GETRANDOM
+ res = getrandom(dummy_key + dummy_key_avail,
+ sizeof(dummy_key) - dummy_key_avail, GRND_NONBLOCK);
if (res < 0) {
- wpa_printf(MSG_ERROR, "random: Cannot read from /dev/random: "
- "%s", strerror(errno));
- res = 0;
+ if (errno == ENOSYS) {
+ wpa_printf(MSG_DEBUG,
+ "random: getrandom() not supported, falling back to /dev/random");
+ } else {
+ wpa_printf(MSG_INFO,
+ "random: no data from getrandom(): %s",
+ strerror(errno));
+ res = 0;
+ }
}
- wpa_printf(MSG_DEBUG, "random: Got %u/%u bytes from "
- "/dev/random", (unsigned) res,
+#else /* CONFIG_GETRANDOM */
+ res = -1;
+#endif /* CONFIG_GETRANDOM */
+ if (res < 0) {
+ fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
+ if (fd < 0) {
+ wpa_printf(MSG_ERROR,
+ "random: Cannot open /dev/random: %s",
+ strerror(errno));
+ return -1;
+ }
+
+ res = read(fd, dummy_key + dummy_key_avail,
+ sizeof(dummy_key) - dummy_key_avail);
+ if (res < 0) {
+ wpa_printf(MSG_ERROR,
+ "random: Cannot read from /dev/random: %s",
+ strerror(errno));
+ res = 0;
+ }
+ close(fd);
+ }
+
+ wpa_printf(MSG_DEBUG, "random: Got %u/%u random bytes", (unsigned) res,
(unsigned) (sizeof(dummy_key) - dummy_key_avail));
dummy_key_avail += res;
- close(fd);
if (dummy_key_avail == sizeof(dummy_key)) {
if (own_pool_ready < MIN_READY_MARK)
@@ -261,7 +288,7 @@ int random_pool_ready(void)
}
wpa_printf(MSG_INFO, "random: Only %u/%u bytes of strong "
- "random data available from /dev/random",
+ "random data available",
(unsigned) dummy_key_avail, (unsigned) sizeof(dummy_key));
if (own_pool_ready >= MIN_READY_MARK ||
@@ -356,7 +383,6 @@ static void random_read_entropy(void)
own_pool_ready = (u8) buf[0];
random_add_randomness(buf + 1, RANDOM_ENTROPY_SIZE);
- random_entropy_file_read = 1;
os_free(buf);
wpa_printf(MSG_DEBUG, "random: Added entropy from %s "
"(own_pool_ready=%u)",
@@ -414,6 +440,19 @@ void random_init(const char *entropy_file)
if (random_fd >= 0)
return;
+#ifdef CONFIG_GETRANDOM
+ {
+ u8 dummy;
+
+ if (getrandom(&dummy, 0, GRND_NONBLOCK) == 0 ||
+ errno != ENOSYS) {
+ wpa_printf(MSG_DEBUG,
+ "random: getrandom() support available");
+ return;
+ }
+ }
+#endif /* CONFIG_GETRANDOM */
+
random_fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
if (random_fd < 0) {
wpa_printf(MSG_ERROR, "random: Cannot open /dev/random: %s",
diff --git a/freebsd/contrib/wpa/src/crypto/sha256-internal.c b/freebsd/contrib/wpa/src/crypto/sha256-internal.c
index 174bf3c4..8b07ab01 100644
--- a/freebsd/contrib/wpa/src/crypto/sha256-internal.c
+++ b/freebsd/contrib/wpa/src/crypto/sha256-internal.c
@@ -71,7 +71,7 @@ static const unsigned long K[64] = {
( ((((unsigned long) (x) & 0xFFFFFFFFUL) >> (unsigned long) ((y) & 31)) | \
((unsigned long) (x) << (unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL)
#define Ch(x,y,z) (z ^ (x & (y ^ z)))
-#define Maj(x,y,z) (((x | y) & z) | (x & y))
+#define Maj(x,y,z) (((x | y) & z) | (x & y))
#define S(x, n) RORc((x), (n))
#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n))
#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22))
@@ -102,7 +102,7 @@ static int sha256_compress(struct sha256_state *md, unsigned char *buf)
for (i = 16; i < 64; i++) {
W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) +
W[i - 16];
- }
+ }
/* Compress */
#define RND(a,b,c,d,e,f,g,h,i) \
@@ -113,7 +113,7 @@ static int sha256_compress(struct sha256_state *md, unsigned char *buf)
for (i = 0; i < 64; ++i) {
RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i);
- t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4];
+ t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4];
S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;
}
diff --git a/freebsd/contrib/wpa/src/crypto/sha384.h b/freebsd/contrib/wpa/src/crypto/sha384.h
index 3deafa59..22414253 100644
--- a/freebsd/contrib/wpa/src/crypto/sha384.h
+++ b/freebsd/contrib/wpa/src/crypto/sha384.h
@@ -1,6 +1,6 @@
/*
* SHA384 hash implementation and interface functions
- * Copyright (c) 2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2015-2017, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -15,10 +15,13 @@ int hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem,
const u8 *addr[], const size_t *len, u8 *mac);
int hmac_sha384(const u8 *key, size_t key_len, const u8 *data,
size_t data_len, u8 *mac);
-void sha384_prf(const u8 *key, size_t key_len, const char *label,
- const u8 *data, size_t data_len, u8 *buf, size_t buf_len);
-void sha384_prf_bits(const u8 *key, size_t key_len, const char *label,
- const u8 *data, size_t data_len, u8 *buf,
- size_t buf_len_bits);
+int sha384_prf(const u8 *key, size_t key_len, const char *label,
+ const u8 *data, size_t data_len, u8 *buf, size_t buf_len);
+int sha384_prf_bits(const u8 *key, size_t key_len, const char *label,
+ const u8 *data, size_t data_len, u8 *buf,
+ size_t buf_len_bits);
+int hmac_sha384_kdf(const u8 *secret, size_t secret_len,
+ const char *label, const u8 *seed, size_t seed_len,
+ u8 *out, size_t outlen);
#endif /* SHA384_H */
diff --git a/freebsd/contrib/wpa/src/crypto/sha512.h b/freebsd/contrib/wpa/src/crypto/sha512.h
new file mode 100644
index 00000000..8e64c8b1
--- /dev/null
+++ b/freebsd/contrib/wpa/src/crypto/sha512.h
@@ -0,0 +1,27 @@
+/*
+ * SHA512 hash implementation and interface functions
+ * Copyright (c) 2015-2017, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef SHA512_H
+#define SHA512_H
+
+#define SHA512_MAC_LEN 64
+
+int hmac_sha512_vector(const u8 *key, size_t key_len, size_t num_elem,
+ const u8 *addr[], const size_t *len, u8 *mac);
+int hmac_sha512(const u8 *key, size_t key_len, const u8 *data,
+ size_t data_len, u8 *mac);
+int sha512_prf(const u8 *key, size_t key_len, const char *label,
+ const u8 *data, size_t data_len, u8 *buf, size_t buf_len);
+int sha512_prf_bits(const u8 *key, size_t key_len, const char *label,
+ const u8 *data, size_t data_len, u8 *buf,
+ size_t buf_len_bits);
+int hmac_sha512_kdf(const u8 *secret, size_t secret_len,
+ const char *label, const u8 *seed, size_t seed_len,
+ u8 *out, size_t outlen);
+
+#endif /* SHA512_H */
diff --git a/freebsd/contrib/wpa/src/crypto/tls.h b/freebsd/contrib/wpa/src/crypto/tls.h
index 11d504a9..8bdb91ff 100644
--- a/freebsd/contrib/wpa/src/crypto/tls.h
+++ b/freebsd/contrib/wpa/src/crypto/tls.h
@@ -41,6 +41,8 @@ enum tls_fail_reason {
TLS_FAIL_SERVER_CHAIN_PROBE = 8,
TLS_FAIL_DOMAIN_SUFFIX_MISMATCH = 9,
TLS_FAIL_DOMAIN_MISMATCH = 10,
+ TLS_FAIL_INSUFFICIENT_KEY_LEN = 11,
+ TLS_FAIL_DN_MISMATCH = 12,
};
@@ -63,6 +65,7 @@ union tls_event_data {
size_t hash_len;
const char *altsubject[TLS_MAX_ALT_SUBJECT];
int num_altsubject;
+ const char *serial_num;
} peer_cert;
struct {
@@ -80,6 +83,8 @@ struct tls_config {
int cert_in_cb;
const char *openssl_ciphers;
unsigned int tls_session_lifetime;
+ unsigned int crl_reload_interval;
+ unsigned int tls_flags;
void (*event_cb)(void *ctx, enum tls_event ev,
union tls_event_data *data);
@@ -97,6 +102,12 @@ struct tls_config {
#define TLS_CONN_DISABLE_TLSv1_0 BIT(8)
#define TLS_CONN_EXT_CERT_CHECK BIT(9)
#define TLS_CONN_REQUIRE_OCSP_ALL BIT(10)
+#define TLS_CONN_SUITEB BIT(11)
+#define TLS_CONN_SUITEB_NO_ECDH BIT(12)
+#define TLS_CONN_DISABLE_TLSv1_3 BIT(13)
+#define TLS_CONN_ENABLE_TLSv1_0 BIT(14)
+#define TLS_CONN_ENABLE_TLSv1_1 BIT(15)
+#define TLS_CONN_ENABLE_TLSv1_2 BIT(16)
/**
* struct tls_connection_params - Parameters for TLS connection
@@ -109,12 +120,19 @@ struct tls_config {
* %NULL to allow all subjects
* @altsubject_match: String to match in the alternative subject of the peer
* certificate or %NULL to allow all alternative subjects
- * @suffix_match: String to suffix match in the dNSName or CN of the peer
- * certificate or %NULL to allow all domain names. This may allow subdomains an
- * wildcard certificates. Each domain name label must have a full match.
+ * @suffix_match: Semicolon deliminated string of values to suffix match against
+ * the dNSName or CN of the peer certificate or %NULL to allow all domain names.
+ * This may allow subdomains and wildcard certificates. Each domain name label
+ * must have a full case-insensitive match.
* @domain_match: String to match in the dNSName or CN of the peer
* certificate or %NULL to allow all domain names. This requires a full,
* case-insensitive match.
+ *
+ * More than one match string can be provided by using semicolons to
+ * separate the strings (e.g., example.org;example.com). When multiple
+ * strings are specified, a match with any one of the values is
+ * considered a sufficient match for the certificate, i.e., the
+ * conditions are ORed together.
* @client_cert: File or reference name for client X.509 certificate in PEM or
* DER format
* @client_cert_blob: client_cert as inlined data or %NULL if not used
@@ -138,12 +156,15 @@ struct tls_config {
* @cert_id: the certificate's id when using engine
* @ca_cert_id: the CA certificate's id when using engine
* @openssl_ciphers: OpenSSL cipher configuration
+ * @openssl_ecdh_curves: OpenSSL ECDH curve configuration. %NULL for auto if
+ * supported, empty string to disable, or a colon-separated curve list.
* @flags: Parameter options (TLS_CONN_*)
* @ocsp_stapling_response: DER encoded file with cached OCSP stapling response
* or %NULL if OCSP is not enabled
* @ocsp_stapling_response_multi: DER encoded file with cached OCSP stapling
* response list (OCSPResponseList for ocsp_multi in RFC 6961) or %NULL if
* ocsp_multi is not enabled
+ * @check_cert_subject: Client certificate subject name matching string
*
* TLS connection parameters to be configured with tls_connection_set_params()
* and tls_global_set_params().
@@ -181,10 +202,12 @@ struct tls_connection_params {
const char *cert_id;
const char *ca_cert_id;
const char *openssl_ciphers;
+ const char *openssl_ecdh_curves;
unsigned int flags;
const char *ocsp_stapling_response;
const char *ocsp_stapling_response_multi;
+ const char *check_cert_subject;
};
@@ -248,6 +271,18 @@ void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn);
int tls_connection_established(void *tls_ctx, struct tls_connection *conn);
/**
+ * tls_connection_peer_serial_num - Fetch peer certificate serial number
+ * @tls_ctx: TLS context data from tls_init()
+ * @conn: Connection context data from tls_connection_init()
+ * Returns: Allocated string buffer containing the peer certificate serial
+ * number or %NULL on error.
+ *
+ * The caller is responsible for freeing the returned buffer with os_free().
+ */
+char * tls_connection_peer_serial_num(void *tls_ctx,
+ struct tls_connection *conn);
+
+/**
* tls_connection_shutdown - Shutdown TLS connection
* @tls_ctx: TLS context data from tls_init()
* @conn: Connection context data from tls_connection_init()
@@ -303,9 +338,11 @@ int __must_check tls_global_set_params(
* @tls_ctx: TLS context data from tls_init()
* @check_crl: 0 = do not verify CRLs, 1 = verify CRL for the user certificate,
* 2 = verify CRL for all certificates
+ * @strict: 0 = allow CRL time errors, 1 = do not allow CRL time errors
* Returns: 0 on success, -1 on failure
*/
-int __must_check tls_global_set_verify(void *tls_ctx, int check_crl);
+int __must_check tls_global_set_verify(void *tls_ctx, int check_crl,
+ int strict);
/**
* tls_connection_set_verify - Set certificate verification options
@@ -340,15 +377,21 @@ int __must_check tls_connection_get_random(void *tls_ctx,
* @tls_ctx: TLS context data from tls_init()
* @conn: Connection context data from tls_connection_init()
* @label: Label (e.g., description of the key) for PRF
+ * @context: Optional extra upper-layer context (max len 2^16)
+ * @context_len: The length of the context value
* @out: Buffer for output data from TLS-PRF
* @out_len: Length of the output buffer
* Returns: 0 on success, -1 on failure
*
- * Exports keying material using the mechanism described in RFC 5705.
+ * Exports keying material using the mechanism described in RFC 5705. If
+ * context is %NULL, context is not provided; otherwise, context is provided
+ * (including the case of empty context with context_len == 0).
*/
int __must_check tls_connection_export_key(void *tls_ctx,
struct tls_connection *conn,
const char *label,
+ const u8 *context,
+ size_t context_len,
u8 *out, size_t out_len);
/**
diff --git a/freebsd/contrib/wpa/src/crypto/tls_internal.c b/freebsd/contrib/wpa/src/crypto/tls_internal.c
index c6f65dc0..ff2fcb7d 100644
--- a/freebsd/contrib/wpa/src/crypto/tls_internal.c
+++ b/freebsd/contrib/wpa/src/crypto/tls_internal.c
@@ -2,7 +2,7 @@
/*
* TLS interface functions and an internal TLS implementation
- * Copyright (c) 2004-2011, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -179,6 +179,14 @@ int tls_connection_established(void *tls_ctx, struct tls_connection *conn)
}
+char * tls_connection_peer_serial_num(void *tls_ctx,
+ struct tls_connection *conn)
+{
+ /* TODO */
+ return NULL;
+}
+
+
int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn)
{
#ifdef CONFIG_TLS_INTERNAL_CLIENT
@@ -242,6 +250,12 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
return -1;
}
+ if (params->openssl_ecdh_curves) {
+ wpa_printf(MSG_INFO, "TLS: openssl_ecdh_curves not supported");
+ tlsv1_cred_free(cred);
+ return -1;
+ }
+
if (tlsv1_set_ca_cert(cred, params->ca_cert,
params->ca_cert_blob, params->ca_cert_blob_len,
params->ca_path)) {
@@ -297,6 +311,9 @@ int tls_global_set_params(void *tls_ctx,
struct tls_global *global = tls_ctx;
struct tlsv1_credentials *cred;
+ if (params->check_cert_subject)
+ return -1; /* not yet supported */
+
/* Currently, global parameters are only set when running in server
* mode. */
global->server = 1;
@@ -347,7 +364,7 @@ int tls_global_set_params(void *tls_ctx,
}
-int tls_global_set_verify(void *tls_ctx, int check_crl)
+int tls_global_set_verify(void *tls_ctx, int check_crl, int strict)
{
struct tls_global *global = tls_ctx;
global->check_crl = check_crl;
@@ -397,7 +414,8 @@ static int tls_get_keyblock_size(struct tls_connection *conn)
static int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
- const char *label, int server_random_first,
+ const char *label, const u8 *context,
+ size_t context_len, int server_random_first,
int skip_keyblock, u8 *out, size_t out_len)
{
int ret = -1, skip = 0;
@@ -416,15 +434,15 @@ static int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
#ifdef CONFIG_TLS_INTERNAL_CLIENT
if (conn->client) {
- ret = tlsv1_client_prf(conn->client, label,
- server_random_first,
+ ret = tlsv1_client_prf(conn->client, label, context,
+ context_len, server_random_first,
_out, skip + out_len);
}
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
#ifdef CONFIG_TLS_INTERNAL_SERVER
if (conn->server) {
- ret = tlsv1_server_prf(conn->server, label,
- server_random_first,
+ ret = tlsv1_server_prf(conn->server, label, context,
+ context_len, server_random_first,
_out, skip + out_len);
}
#endif /* CONFIG_TLS_INTERNAL_SERVER */
@@ -437,17 +455,19 @@ static int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
- const char *label, u8 *out, size_t out_len)
+ const char *label, const u8 *context,
+ size_t context_len, u8 *out, size_t out_len)
{
- return tls_connection_prf(tls_ctx, conn, label, 0, 0, out, out_len);
+ return tls_connection_prf(tls_ctx, conn, label, context, context_len,
+ 0, 0, out, out_len);
}
int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn,
u8 *out, size_t out_len)
{
- return tls_connection_prf(tls_ctx, conn, "key expansion", 1, 1, out,
- out_len);
+ return tls_connection_prf(tls_ctx, conn, "key expansion", NULL, 0,
+ 1, 1, out, out_len);
}
@@ -714,12 +734,20 @@ int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn,
int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn)
{
+#ifdef CONFIG_TLS_INTERNAL_SERVER
+ if (conn->server)
+ return tlsv1_server_get_failed(conn->server);
+#endif /* CONFIG_TLS_INTERNAL_SERVER */
return 0;
}
int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn)
{
+#ifdef CONFIG_TLS_INTERNAL_SERVER
+ if (conn->server)
+ return tlsv1_server_get_read_alerts(conn->server);
+#endif /* CONFIG_TLS_INTERNAL_SERVER */
return 0;
}
@@ -727,6 +755,10 @@ int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn)
int tls_connection_get_write_alerts(void *tls_ctx,
struct tls_connection *conn)
{
+#ifdef CONFIG_TLS_INTERNAL_SERVER
+ if (conn->server)
+ return tlsv1_server_get_write_alerts(conn->server);
+#endif /* CONFIG_TLS_INTERNAL_SERVER */
return 0;
}
diff --git a/freebsd/contrib/wpa/src/drivers/driver.h b/freebsd/contrib/wpa/src/drivers/driver.h
index a449cc93..e7c8f318 100644
--- a/freebsd/contrib/wpa/src/drivers/driver.h
+++ b/freebsd/contrib/wpa/src/drivers/driver.h
@@ -1,6 +1,6 @@
/*
* Driver interface definition
- * Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2017, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -21,6 +21,10 @@
#include "common/defs.h"
#include "common/ieee802_11_defs.h"
+#include "common/wpa_common.h"
+#ifdef CONFIG_MACSEC
+#include "pae/ieee802_1x_kay.h"
+#endif /* CONFIG_MACSEC */
#include "utils/list.h"
#define HOSTAPD_CHAN_DISABLED 0x00000001
@@ -54,6 +58,16 @@
#define HOSTAPD_CHAN_VHT_130_30 0x04000000
#define HOSTAPD_CHAN_VHT_150_10 0x08000000
+/* Allowed bandwidth mask */
+enum hostapd_chan_width_attr {
+ HOSTAPD_CHAN_WIDTH_10 = BIT(0),
+ HOSTAPD_CHAN_WIDTH_20 = BIT(1),
+ HOSTAPD_CHAN_WIDTH_40P = BIT(2),
+ HOSTAPD_CHAN_WIDTH_40M = BIT(3),
+ HOSTAPD_CHAN_WIDTH_80 = BIT(4),
+ HOSTAPD_CHAN_WIDTH_160 = BIT(5),
+};
+
/* Filter gratuitous ARP */
#define WPA_DATA_FRAME_FILTER_FLAG_ARP BIT(0)
/* Filter unsolicited Neighbor Advertisement */
@@ -61,6 +75,10 @@
/* Filter unicast IP packets encrypted using the GTK */
#define WPA_DATA_FRAME_FILTER_FLAG_GTK BIT(2)
+#define HOSTAPD_DFS_REGION_FCC 1
+#define HOSTAPD_DFS_REGION_ETSI 2
+#define HOSTAPD_DFS_REGION_JP 3
+
/**
* enum reg_change_initiator - Regulatory change initiator
*/
@@ -103,6 +121,13 @@ struct hostapd_channel_data {
int flag;
/**
+ * allowed_bw - Allowed channel width bitmask
+ *
+ * See enum hostapd_chan_width_attr.
+ */
+ u32 allowed_bw;
+
+ /**
* max_tx_power - Regulatory transmit power limit in dBm
*/
u8 max_tx_power;
@@ -133,6 +158,29 @@ struct hostapd_channel_data {
unsigned int dfs_cac_ms;
};
+#define HE_MAX_NUM_SS 8
+#define HE_MAX_PHY_CAPAB_SIZE 3
+
+/**
+ * struct he_ppe_threshold - IEEE 802.11ax HE PPE Threshold
+ */
+struct he_ppe_threshold {
+ u32 numss_m1;
+ u32 ru_count;
+ u32 ppet16_ppet8_ru3_ru0[HE_MAX_NUM_SS];
+};
+
+/**
+ * struct he_capabilities - IEEE 802.11ax HE capabilities
+ */
+struct he_capabilities {
+ u8 he_supported;
+ u32 phy_cap[HE_MAX_PHY_CAPAB_SIZE];
+ u32 mac_cap;
+ u32 mcs;
+ struct he_ppe_threshold ppet;
+};
+
#define HOSTAPD_MODE_FLAG_HT_INFO_KNOWN BIT(0)
#define HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN BIT(1)
@@ -191,6 +239,11 @@ struct hostapd_hw_modes {
u8 vht_mcs_set[8];
unsigned int flags; /* HOSTAPD_MODE_FLAG_* */
+
+ /**
+ * he_capab - HE (IEEE 802.11ax) capabilities
+ */
+ struct he_capabilities he_capab;
};
@@ -233,6 +286,9 @@ struct hostapd_hw_modes {
* @est_throughput: Estimated throughput in kbps (this is calculated during
* scan result processing if left zero by the driver wrapper)
* @snr: Signal-to-noise ratio in dB (calculated during scan result processing)
+ * @parent_tsf: Time when the Beacon/Probe Response frame was received in terms
+ * of TSF of the BSS specified by %tsf_bssid.
+ * @tsf_bssid: The BSS that %parent_tsf TSF time refers to.
* @ie_len: length of the following IE field in octets
* @beacon_ie_len: length of the following Beacon IE field in octets
*
@@ -263,6 +319,8 @@ struct wpa_scan_res {
unsigned int age;
unsigned int est_throughput;
int snr;
+ u64 parent_tsf;
+ u8 tsf_bssid[ETH_ALEN];
size_t ie_len;
size_t beacon_ie_len;
/* Followed by ie_len + beacon_ie_len octets of IE data */
@@ -447,6 +505,15 @@ struct wpa_driver_scan_params {
unsigned int sched_scan_plans_num;
/**
+ * sched_scan_start_delay - Delay to use before starting the first scan
+ *
+ * Delay (in seconds) before scheduling first scan plan cycle. The
+ * driver may ignore this parameter and start immediately (or at any
+ * other time), if this feature is not supported.
+ */
+ u32 sched_scan_start_delay;
+
+ /**
* bssid - Specific BSSID to scan for
*
* This optional parameter can be used to replace the default wildcard
@@ -455,6 +522,80 @@ struct wpa_driver_scan_params {
*/
const u8 *bssid;
+ /**
+ * scan_cookie - Unique identification representing the scan request
+ *
+ * This scan_cookie carries a unique identification representing the
+ * scan request if the host driver/kernel supports concurrent scan
+ * requests. This cookie is returned from the corresponding driver
+ * interface.
+ *
+ * Note: Unlike other parameters in this structure, scan_cookie is used
+ * only to return information instead of setting parameters for the
+ * scan.
+ */
+ u64 scan_cookie;
+
+ /**
+ * duration - Dwell time on each channel
+ *
+ * This optional parameter can be used to set the dwell time on each
+ * channel. In TUs.
+ */
+ u16 duration;
+
+ /**
+ * duration_mandatory - Whether the specified duration is mandatory
+ *
+ * If this is set, the duration specified by the %duration field is
+ * mandatory (and the driver should reject the scan request if it is
+ * unable to comply with the specified duration), otherwise it is the
+ * maximum duration and the actual duration may be shorter.
+ */
+ unsigned int duration_mandatory:1;
+
+ /**
+ * relative_rssi_set - Whether relative RSSI parameters are set
+ */
+ unsigned int relative_rssi_set:1;
+
+ /**
+ * relative_rssi - Relative RSSI for reporting better BSSs
+ *
+ * Amount of RSSI by which a BSS should be better than the current
+ * connected BSS to report the new BSS to user space.
+ */
+ s8 relative_rssi;
+
+ /**
+ * relative_adjust_band - Band to which RSSI should be adjusted
+ *
+ * The relative_adjust_rssi should be added to the band specified
+ * by relative_adjust_band.
+ */
+ enum set_band relative_adjust_band;
+
+ /**
+ * relative_adjust_rssi - RSSI to be added to relative_adjust_band
+ *
+ * An amount of relative_band_rssi should be added to the BSSs that
+ * belong to the band specified by relative_adjust_band while comparing
+ * with other bands for BSS reporting.
+ */
+ s8 relative_adjust_rssi;
+
+ /**
+ * oce_scan
+ *
+ * Enable the following OCE scan features: (WFA OCE TechSpec v1.0)
+ * - Accept broadcast Probe Response frame.
+ * - Probe Request frame deferral and suppression.
+ * - Max Channel Time - driver fills FILS request params IE with
+ * Maximum Channel Time.
+ * - Send 1st Probe Request frame in rate of minimum 5.5 Mbps.
+ */
+ unsigned int oce_scan:1;
+
/*
* NOTE: Whenever adding new parameters here, please make sure
* wpa_scan_clone_params() and wpa_scan_free_params() get updated with
@@ -485,17 +626,18 @@ struct wpa_driver_auth_params {
int p2p;
/**
- * sae_data - SAE elements for Authentication frame
+ * auth_data - Additional elements for Authentication frame
*
* This buffer starts with the Authentication transaction sequence
- * number field. If SAE is not used, this pointer is %NULL.
+ * number field. If no special handling of such elements is needed, this
+ * pointer is %NULL. This is used with SAE and FILS.
*/
- const u8 *sae_data;
+ const u8 *auth_data;
/**
- * sae_data_len - Length of sae_data buffer in octets
+ * auth_data_len - Length of auth_data buffer in octets
*/
- size_t sae_data_len;
+ size_t auth_data_len;
};
/**
@@ -577,6 +719,68 @@ struct hostapd_freq_params {
};
/**
+ * struct wpa_driver_sta_auth_params - Authentication parameters
+ * Data for struct wpa_driver_ops::sta_auth().
+ */
+struct wpa_driver_sta_auth_params {
+
+ /**
+ * own_addr - Source address and BSSID for authentication frame
+ */
+ const u8 *own_addr;
+
+ /**
+ * addr - MAC address of the station to associate
+ */
+ const u8 *addr;
+
+ /**
+ * seq - authentication sequence number
+ */
+ u16 seq;
+
+ /**
+ * status - authentication response status code
+ */
+ u16 status;
+
+ /**
+ * ie - authentication frame ie buffer
+ */
+ const u8 *ie;
+
+ /**
+ * len - ie buffer length
+ */
+ size_t len;
+
+ /**
+ * fils_auth - Indicates whether FILS authentication is being performed
+ */
+ int fils_auth;
+
+ /**
+ * fils_anonce - ANonce (required for FILS)
+ */
+ u8 fils_anonce[WPA_NONCE_LEN];
+
+ /**
+ * fils_snonce - SNonce (required for FILS)
+ */
+ u8 fils_snonce[WPA_NONCE_LEN];
+
+ /**
+ * fils_kek - key for encryption (required for FILS)
+ */
+ u8 fils_kek[WPA_KEK_MAX_LEN];
+
+ /**
+ * fils_kek_len - Length of the fils_kek in octets (required for FILS)
+ */
+ size_t fils_kek_len;
+};
+
+/**
* struct wpa_driver_associate_params - Association parameters
* Data for struct wpa_driver_ops::associate().
*/
@@ -639,7 +843,7 @@ struct wpa_driver_associate_params {
* WPA information element to be included in (Re)Association
* Request (including information element id and length). Use
* of this WPA IE is optional. If the driver generates the WPA
- * IE, it can use pairwise_suite, group_suite, and
+ * IE, it can use pairwise_suite, group_suite, group_mgmt_suite, and
* key_mgmt_suite to select proper algorithms. In this case,
* the driver has to notify wpa_supplicant about the used WPA
* IE by generating an event that the interface code will
@@ -679,6 +883,13 @@ struct wpa_driver_associate_params {
unsigned int group_suite;
/**
+ * mgmt_group_suite - Selected group management cipher suite (WPA_CIPHER_*)
+ *
+ * This is usually ignored if @wpa_ie is used.
+ */
+ unsigned int mgmt_group_suite;
+
+ /**
* key_mgmt_suite - Selected key management suite (WPA_KEY_MGMT_*)
*
* This is usually ignored if @wpa_ie is used.
@@ -717,50 +928,13 @@ struct wpa_driver_associate_params {
enum mfp_options mgmt_frame_protection;
/**
- * ft_ies - IEEE 802.11r / FT information elements
- * If the supplicant is using IEEE 802.11r (FT) and has the needed keys
- * for fast transition, this parameter is set to include the IEs that
- * are to be sent in the next FT Authentication Request message.
- * update_ft_ies() handler is called to update the IEs for further
- * FT messages in the sequence.
- *
- * The driver should use these IEs only if the target AP is advertising
- * the same mobility domain as the one included in the MDIE here.
- *
- * In ap_scan=2 mode, the driver can use these IEs when moving to a new
- * AP after the initial association. These IEs can only be used if the
- * target AP is advertising support for FT and is using the same MDIE
- * and SSID as the current AP.
- *
- * The driver is responsible for reporting the FT IEs received from the
- * AP's response using wpa_supplicant_event() with EVENT_FT_RESPONSE
- * type. update_ft_ies() handler will then be called with the FT IEs to
- * include in the next frame in the authentication sequence.
- */
- const u8 *ft_ies;
-
- /**
- * ft_ies_len - Length of ft_ies in bytes
- */
- size_t ft_ies_len;
-
- /**
- * ft_md - FT Mobility domain (6 octets) (also included inside ft_ies)
- *
- * This value is provided to allow the driver interface easier access
- * to the current mobility domain. This value is set to %NULL if no
- * mobility domain is currently active.
- */
- const u8 *ft_md;
-
- /**
* passphrase - RSN passphrase for PSK
*
* This value is made available only for WPA/WPA2-Personal (PSK) and
- * only for drivers that set WPA_DRIVER_FLAGS_4WAY_HANDSHAKE. This is
- * the 8..63 character ASCII passphrase, if available. Please note that
- * this can be %NULL if passphrase was not used to generate the PSK. In
- * that case, the psk field must be used to fetch the PSK.
+ * only for drivers that set WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK. This
+ * is the 8..63 character ASCII passphrase, if available. Please note
+ * that this can be %NULL if passphrase was not used to generate the
+ * PSK. In that case, the psk field must be used to fetch the PSK.
*/
const char *passphrase;
@@ -768,9 +942,9 @@ struct wpa_driver_associate_params {
* psk - RSN PSK (alternative for passphrase for PSK)
*
* This value is made available only for WPA/WPA2-Personal (PSK) and
- * only for drivers that set WPA_DRIVER_FLAGS_4WAY_HANDSHAKE. This is
- * the 32-octet (256-bit) PSK, if available. The driver wrapper should
- * be prepared to handle %NULL value as an error.
+ * only for drivers that set WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK. This
+ * is the 32-octet (256-bit) PSK, if available. The driver wrapper
+ * should be prepared to handle %NULL value as an error.
*/
const u8 *psk;
@@ -882,6 +1056,64 @@ struct wpa_driver_associate_params {
* AP as usual. Valid for DMG network only.
*/
int pbss;
+
+ /**
+ * fils_kek - KEK for FILS association frame protection (AES-SIV)
+ */
+ const u8 *fils_kek;
+
+ /**
+ * fils_kek_len: Length of fils_kek in bytes
+ */
+ size_t fils_kek_len;
+
+ /**
+ * fils_nonces - Nonces for FILS association frame protection
+ * (AES-SIV AAD)
+ */
+ const u8 *fils_nonces;
+
+ /**
+ * fils_nonces_len: Length of fils_nonce in bytes
+ */
+ size_t fils_nonces_len;
+
+ /**
+ * fils_erp_username - Username part of keyName-NAI
+ */
+ const u8 *fils_erp_username;
+
+ /**
+ * fils_erp_username_len - Length of fils_erp_username in bytes
+ */
+ size_t fils_erp_username_len;
+
+ /**
+ * fils_erp_realm - Realm/domain name to use in FILS ERP
+ */
+ const u8 *fils_erp_realm;
+
+ /**
+ * fils_erp_realm_len - Length of fils_erp_realm in bytes
+ */
+ size_t fils_erp_realm_len;
+
+ /**
+ * fils_erp_next_seq_num - The next sequence number to use in FILS ERP
+ * messages
+ */
+ u16 fils_erp_next_seq_num;
+
+ /**
+ * fils_erp_rrk - Re-authentication root key (rRK) for the keyName-NAI
+ * specified by fils_erp_username@fils_erp_realm.
+ */
+ const u8 *fils_erp_rrk;
+
+ /**
+ * fils_erp_rrk_len - Length of fils_erp_rrk in bytes
+ */
+ size_t fils_erp_rrk_len;
};
enum hide_ssid {
@@ -940,6 +1172,22 @@ struct wpa_driver_ap_params {
int *basic_rates;
/**
+ * beacon_rate: Beacon frame data rate
+ *
+ * This parameter can be used to set a specific Beacon frame data rate
+ * for the BSS. The interpretation of this value depends on the
+ * rate_type (legacy: in 100 kbps units, HT: HT-MCS, VHT: VHT-MCS). If
+ * beacon_rate == 0 and rate_type == 0 (BEACON_RATE_LEGACY), the default
+ * Beacon frame data rate is used.
+ */
+ unsigned int beacon_rate;
+
+ /**
+ * beacon_rate_type: Beacon data rate type (legacy/HT/VHT)
+ */
+ enum beacon_rate_type rate_type;
+
+ /**
* proberesp - Probe Response template
*
* This is used by drivers that reply to Probe Requests internally in
@@ -1115,6 +1363,44 @@ struct wpa_driver_ap_params {
* infrastructure BSS. Valid only for DMG network.
*/
int pbss;
+
+ /**
+ * multicast_to_unicast - Whether to use multicast_to_unicast
+ *
+ * If this is non-zero, the AP is requested to perform multicast to
+ * unicast conversion for ARP, IPv4, and IPv6 frames (possibly within
+ * 802.1Q). If enabled, such frames are to be sent to each station
+ * separately, with the DA replaced by their own MAC address rather
+ * than the group address.
+ *
+ * Note that this may break certain expectations of the receiver, such
+ * as the ability to drop unicast IP packets received within multicast
+ * L2 frames, or the ability to not send ICMP destination unreachable
+ * messages for packets received in L2 multicast (which is required,
+ * but the receiver can't tell the difference if this new option is
+ * enabled.)
+ *
+ * This also doesn't implement the 802.11 DMS (directed multicast
+ * service).
+ */
+ int multicast_to_unicast;
+
+ /**
+ * ftm_responder - Whether FTM responder is enabled
+ */
+ int ftm_responder;
+
+ /**
+ * lci - Binary data, the content of an LCI report IE with type 8 as
+ * defined in IEEE Std 802.11-2016, 9.4.2.22.10
+ */
+ const struct wpabuf *lci;
+
+ /**
+ * civic - Binary data, the content of a measurement report IE with
+ * type 11 as defined in IEEE Std 802.11-2016, 9.4.2.22.13
+ */
+ const struct wpabuf *civic;
};
struct wpa_driver_mesh_bss_params {
@@ -1122,6 +1408,7 @@ struct wpa_driver_mesh_bss_params {
#define WPA_DRIVER_MESH_CONF_FLAG_PEER_LINK_TIMEOUT 0x00000002
#define WPA_DRIVER_MESH_CONF_FLAG_MAX_PEER_LINKS 0x00000004
#define WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE 0x00000008
+#define WPA_DRIVER_MESH_CONF_FLAG_RSSI_THRESHOLD 0x00000010
/*
* TODO: Other mesh configuration parameters would go here.
* See NL80211_MESHCONF_* for all the mesh config parameters.
@@ -1130,6 +1417,7 @@ struct wpa_driver_mesh_bss_params {
int auto_plinks;
int peer_link_timeout;
int max_peer_links;
+ int rssi_threshold;
u16 ht_opmode;
};
@@ -1164,6 +1452,13 @@ struct wpa_driver_capa {
#define WPA_DRIVER_CAPA_KEY_MGMT_WAPI_PSK 0x00000080
#define WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B 0x00000100
#define WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192 0x00000200
+#define WPA_DRIVER_CAPA_KEY_MGMT_OWE 0x00000400
+#define WPA_DRIVER_CAPA_KEY_MGMT_DPP 0x00000800
+#define WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256 0x00001000
+#define WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384 0x00002000
+#define WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256 0x00004000
+#define WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384 0x00008000
+#define WPA_DRIVER_CAPA_KEY_MGMT_SAE 0x00010000
/** Bitfield of supported key management suites */
unsigned int key_mgmt;
@@ -1197,7 +1492,7 @@ struct wpa_driver_capa {
#define WPA_DRIVER_FLAGS_DFS_OFFLOAD 0x00000004
/** Driver takes care of RSN 4-way handshake internally; PMK is configured with
* struct wpa_driver_ops::set_key using alg = WPA_ALG_PMK */
-#define WPA_DRIVER_FLAGS_4WAY_HANDSHAKE 0x00000008
+#define WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X 0x00000008
/** Driver is for a wired Ethernet interface */
#define WPA_DRIVER_FLAGS_WIRED 0x00000010
/** Driver provides separate commands for authentication and association (SME in
@@ -1286,6 +1581,43 @@ struct wpa_driver_capa {
#define WPA_DRIVER_FLAGS_FULL_AP_CLIENT_STATE 0x0000010000000000ULL
/** Driver supports P2P Listen offload */
#define WPA_DRIVER_FLAGS_P2P_LISTEN_OFFLOAD 0x0000020000000000ULL
+/** Driver supports FILS */
+#define WPA_DRIVER_FLAGS_SUPPORT_FILS 0x0000040000000000ULL
+/** Driver supports Beacon frame TX rate configuration (legacy rates) */
+#define WPA_DRIVER_FLAGS_BEACON_RATE_LEGACY 0x0000080000000000ULL
+/** Driver supports Beacon frame TX rate configuration (HT rates) */
+#define WPA_DRIVER_FLAGS_BEACON_RATE_HT 0x0000100000000000ULL
+/** Driver supports Beacon frame TX rate configuration (VHT rates) */
+#define WPA_DRIVER_FLAGS_BEACON_RATE_VHT 0x0000200000000000ULL
+/** Driver supports mgmt_tx with random TX address in non-connected state */
+#define WPA_DRIVER_FLAGS_MGMT_TX_RANDOM_TA 0x0000400000000000ULL
+/** Driver supports mgmt_tx with random TX addr in connected state */
+#define WPA_DRIVER_FLAGS_MGMT_TX_RANDOM_TA_CONNECTED 0x0000800000000000ULL
+/** Driver supports better BSS reporting with sched_scan in connected mode */
+#define WPA_DRIVER_FLAGS_SCHED_SCAN_RELATIVE_RSSI 0x0001000000000000ULL
+/** Driver supports HE capabilities */
+#define WPA_DRIVER_FLAGS_HE_CAPABILITIES 0x0002000000000000ULL
+/** Driver supports FILS shared key offload */
+#define WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD 0x0004000000000000ULL
+/** Driver supports all OCE STA specific mandatory features */
+#define WPA_DRIVER_FLAGS_OCE_STA 0x0008000000000000ULL
+/** Driver supports all OCE AP specific mandatory features */
+#define WPA_DRIVER_FLAGS_OCE_AP 0x0010000000000000ULL
+/**
+ * Driver supports all OCE STA-CFON specific mandatory features only.
+ * If a driver sets this bit but not the %WPA_DRIVER_FLAGS_OCE_AP, the
+ * userspace shall assume that this driver may not support all OCE AP
+ * functionality but can support only OCE STA-CFON functionality.
+ */
+#define WPA_DRIVER_FLAGS_OCE_STA_CFON 0x0020000000000000ULL
+/** Driver supports MFP-optional in the connect command */
+#define WPA_DRIVER_FLAGS_MFP_OPTIONAL 0x0040000000000000ULL
+/** Driver is a self-managed regulatory device */
+#define WPA_DRIVER_FLAGS_SELF_MANAGED_REGULATORY 0x0080000000000000ULL
+/** Driver supports FTM responder functionality */
+#define WPA_DRIVER_FLAGS_FTM_RESPONDER 0x0100000000000000ULL
+/** Driver support 4-way handshake offload for WPA-Personal */
+#define WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK 0x0200000000000000ULL
u64 flags;
#define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \
@@ -1386,6 +1718,11 @@ struct wpa_driver_capa {
*/
#define WPA_DRIVER_FLAGS_SUPPORT_RRM 0x00000010
+/** Driver supports setting the scan dwell time */
+#define WPA_DRIVER_FLAGS_SUPPORT_SET_SCAN_DWELL 0x00000020
+/** Driver supports Beacon Report Measurement */
+#define WPA_DRIVER_FLAGS_SUPPORT_BEACON_REPORT 0x00000040
+
u32 rrm_flags;
/* Driver concurrency capabilities */
@@ -1402,18 +1739,35 @@ struct wpa_driver_capa {
struct hostapd_data;
+#define STA_DRV_DATA_TX_MCS BIT(0)
+#define STA_DRV_DATA_RX_MCS BIT(1)
+#define STA_DRV_DATA_TX_VHT_MCS BIT(2)
+#define STA_DRV_DATA_RX_VHT_MCS BIT(3)
+#define STA_DRV_DATA_TX_VHT_NSS BIT(4)
+#define STA_DRV_DATA_RX_VHT_NSS BIT(5)
+#define STA_DRV_DATA_TX_SHORT_GI BIT(6)
+#define STA_DRV_DATA_RX_SHORT_GI BIT(7)
+#define STA_DRV_DATA_LAST_ACK_RSSI BIT(8)
+
struct hostap_sta_driver_data {
unsigned long rx_packets, tx_packets;
unsigned long long rx_bytes, tx_bytes;
int bytes_64bit; /* whether 64-bit byte counters are supported */
unsigned long current_tx_rate;
+ unsigned long current_rx_rate;
unsigned long inactive_msec;
- unsigned long flags;
+ unsigned long flags; /* bitfield of STA_DRV_DATA_* */
unsigned long num_ps_buf_frames;
unsigned long tx_retry_failed;
unsigned long tx_retry_count;
- int last_rssi;
- int last_ack_rssi;
+ s8 last_ack_rssi;
+ s8 signal;
+ u8 rx_vhtmcs;
+ u8 tx_vhtmcs;
+ u8 rx_mcs;
+ u8 tx_mcs;
+ u8 rx_vht_nss;
+ u8 tx_vht_nss;
};
struct hostapd_sta_add_params {
@@ -1576,19 +1930,32 @@ enum wnm_oper {
WNM_SLEEP_TFS_IE_DEL /* AP delete the TFS IE */
};
-/* enum chan_width - Channel width definitions */
-enum chan_width {
- CHAN_WIDTH_20_NOHT,
- CHAN_WIDTH_20,
- CHAN_WIDTH_40,
- CHAN_WIDTH_80,
- CHAN_WIDTH_80P80,
- CHAN_WIDTH_160,
- CHAN_WIDTH_UNKNOWN
+/* enum smps_mode - SMPS mode definitions */
+enum smps_mode {
+ SMPS_AUTOMATIC,
+ SMPS_OFF,
+ SMPS_DYNAMIC,
+ SMPS_STATIC,
+
+ /* Keep last */
+ SMPS_INVALID,
};
+#define WPA_INVALID_NOISE 9999
+
/**
* struct wpa_signal_info - Information about channel signal quality
+ * @frequency: control frequency
+ * @above_threshold: true if the above threshold was crossed
+ * (relevant for a CQM event)
+ * @current_signal: in dBm
+ * @avg_signal: in dBm
+ * @avg_beacon_signal: in dBm
+ * @current_noise: %WPA_INVALID_NOISE if not supported
+ * @current_txrate: current TX rate
+ * @chanwidth: channel width
+ * @center_frq1: center frequency for the first segment
+ * @center_frq2: center frequency for the second segment (if relevant)
*/
struct wpa_signal_info {
u32 frequency;
@@ -1604,6 +1971,26 @@ struct wpa_signal_info {
};
/**
+ * struct wpa_channel_info - Information about the current channel
+ * @frequency: Center frequency of the primary 20 MHz channel
+ * @chanwidth: Width of the current operating channel
+ * @sec_channel: Location of the secondary 20 MHz channel (either +1 or -1).
+ * This field is only filled in when using a 40 MHz channel.
+ * @center_frq1: Center frequency of frequency segment 0
+ * @center_frq2: Center frequency of frequency segment 1 (for 80+80 channels)
+ * @seg1_idx: Frequency segment 1 index when using a 80+80 channel. This is
+ * derived from center_frq2 for convenience.
+ */
+struct wpa_channel_info {
+ u32 frequency;
+ enum chan_width chanwidth;
+ int sec_channel;
+ int center_frq1;
+ int center_frq2;
+ u8 seg1_idx;
+};
+
+/**
* struct beacon_data - Beacon data
* @head: Head portion of Beacon frame (before TIM IE)
* @tail: Tail portion of Beacon frame (after TIM IE)
@@ -1720,6 +2107,69 @@ struct drv_acs_params {
const int *freq_list;
};
+struct wpa_bss_trans_info {
+ u8 mbo_transition_reason;
+ u8 n_candidates;
+ u8 *bssid;
+};
+
+struct wpa_bss_candidate_info {
+ u8 num;
+ struct candidate_list {
+ u8 bssid[ETH_ALEN];
+ u8 is_accept;
+ u32 reject_reason;
+ } *candidates;
+};
+
+struct wpa_pmkid_params {
+ const u8 *bssid;
+ const u8 *ssid;
+ size_t ssid_len;
+ const u8 *fils_cache_id;
+ const u8 *pmkid;
+ const u8 *pmk;
+ size_t pmk_len;
+};
+
+/* Mask used to specify which connection parameters have to be updated */
+enum wpa_drv_update_connect_params_mask {
+ WPA_DRV_UPDATE_ASSOC_IES = BIT(0),
+ WPA_DRV_UPDATE_FILS_ERP_INFO = BIT(1),
+ WPA_DRV_UPDATE_AUTH_TYPE = BIT(2),
+};
+
+/**
+ * struct external_auth - External authentication trigger parameters
+ *
+ * These are used across the external authentication request and event
+ * interfaces.
+ * @action: Action type / trigger for external authentication. Only significant
+ * for the event interface.
+ * @bssid: BSSID of the peer with which the authentication has to happen. Used
+ * by both the request and event interface.
+ * @ssid: SSID of the AP. Used by both the request and event interface.
+ * @ssid_len: SSID length in octets.
+ * @key_mgmt_suite: AKM suite of the respective authentication. Optional for
+ * the request interface.
+ * @status: Status code, %WLAN_STATUS_SUCCESS for successful authentication,
+ * use %WLAN_STATUS_UNSPECIFIED_FAILURE if wpa_supplicant cannot give
+ * the real status code for failures. Used only for the request interface
+ * from user space to the driver.
+ * @pmkid: Generated PMKID as part of external auth exchange (e.g., SAE).
+ */
+struct external_auth {
+ enum {
+ EXT_AUTH_START,
+ EXT_AUTH_ABORT,
+ } action;
+ const u8 *bssid;
+ const u8 *ssid;
+ size_t ssid_len;
+ unsigned int key_mgmt_suite;
+ u16 status;
+ const u8 *pmkid;
+};
/**
* struct wpa_driver_ops - Driver interface API definition
@@ -1902,13 +2352,14 @@ struct wpa_driver_ops {
/**
* add_pmkid - Add PMKSA cache entry to the driver
* @priv: private driver interface data
- * @bssid: BSSID for the PMKSA cache entry
- * @pmkid: PMKID for the PMKSA cache entry
+ * @params: PMKSA parameters
*
* Returns: 0 on success, -1 on failure
*
* This function is called when a new PMK is received, as a result of
- * either normal authentication or RSN pre-authentication.
+ * either normal authentication or RSN pre-authentication. The PMKSA
+ * parameters are either a set of bssid, pmkid, and pmk; or a set of
+ * ssid, fils_cache_id, pmkid, and pmk.
*
* If the driver generates RSN IE, i.e., it does not use wpa_ie in
* associate(), add_pmkid() can be used to add new PMKSA cache entries
@@ -1916,18 +2367,18 @@ struct wpa_driver_ops {
* driver_ops function does not need to be implemented. Likewise, if
* the driver does not support WPA, this function is not needed.
*/
- int (*add_pmkid)(void *priv, const u8 *bssid, const u8 *pmkid);
+ int (*add_pmkid)(void *priv, struct wpa_pmkid_params *params);
/**
* remove_pmkid - Remove PMKSA cache entry to the driver
* @priv: private driver interface data
- * @bssid: BSSID for the PMKSA cache entry
- * @pmkid: PMKID for the PMKSA cache entry
+ * @params: PMKSA parameters
*
* Returns: 0 on success, -1 on failure
*
* This function is called when the supplicant drops a PMKSA cache
- * entry for any reason.
+ * entry for any reason. The PMKSA parameters are either a set of
+ * bssid and pmkid; or a set of ssid, fils_cache_id, and pmkid.
*
* If the driver generates RSN IE, i.e., it does not use wpa_ie in
* associate(), remove_pmkid() can be used to synchronize PMKSA caches
@@ -1936,7 +2387,7 @@ struct wpa_driver_ops {
* implemented. Likewise, if the driver does not support WPA, this
* function is not needed.
*/
- int (*remove_pmkid)(void *priv, const u8 *bssid, const u8 *pmkid);
+ int (*remove_pmkid)(void *priv, struct wpa_pmkid_params *params);
/**
* flush_pmkid - Flush PMKSA cache
@@ -2051,12 +2502,13 @@ struct wpa_driver_ops {
* @priv: Private driver interface data
* @num_modes: Variable for returning the number of returned modes
* flags: Variable for returning hardware feature flags
+ * @dfs: Variable for returning DFS region (HOSTAPD_DFS_REGION_*)
* Returns: Pointer to allocated hardware data on success or %NULL on
* failure. Caller is responsible for freeing this.
*/
struct hostapd_hw_modes * (*get_hw_feature_data)(void *priv,
u16 *num_modes,
- u16 *flags);
+ u16 *flags, u8 *dfs);
/**
* send_mlme - Send management frame from MLME
@@ -2673,6 +3125,9 @@ struct wpa_driver_ops {
* transmitted on that channel; alternatively the frame may be sent on
* the current operational channel (if in associated state in station
* mode or while operating as an AP.)
+ *
+ * If @src differs from the device MAC address, use of a random
+ * transmitter address is requested for this message exchange.
*/
int (*send_action)(void *priv, unsigned int freq, unsigned int wait,
const u8 *dst, const u8 *src, const u8 *bssid,
@@ -2973,6 +3428,14 @@ struct wpa_driver_ops {
int (*signal_poll)(void *priv, struct wpa_signal_info *signal_info);
/**
+ * channel_info - Get parameters of the current operating channel
+ * @priv: Private driver interface data
+ * @channel_info: Channel info structure
+ * Returns: 0 on success, negative (<0) on failure
+ */
+ int (*channel_info)(void *priv, struct wpa_channel_info *channel_info);
+
+ /**
* set_authmode - Set authentication algorithm(s) for static WEP
* @priv: Private driver interface data
* @authmode: 1=Open System, 2=Shared Key, 3=both
@@ -3058,19 +3521,13 @@ struct wpa_driver_ops {
/**
* sta_auth - Station authentication indication
- * @priv: Private driver interface data
- * @own_addr: Source address and BSSID for authentication frame
- * @addr: MAC address of the station to associate
- * @seq: authentication sequence number
- * @status: authentication response status code
- * @ie: authentication frame ie buffer
- * @len: ie buffer length
+ * @priv: private driver interface data
+ * @params: Station authentication parameters
*
- * This function indicates the driver to send Authentication frame
- * to the station.
+ * Returns: 0 on success, -1 on failure
*/
- int (*sta_auth)(void *priv, const u8 *own_addr, const u8 *addr,
- u16 seq, u16 status, const u8 *ie, size_t len);
+ int (*sta_auth)(void *priv,
+ struct wpa_driver_sta_auth_params *params);
/**
* add_tspec - Add traffic stream
@@ -3259,7 +3716,7 @@ struct wpa_driver_ops {
/**
* status - Get driver interface status information
* @priv: Private driver interface data
- * @buf: Buffer for printing tou the status information
+ * @buf: Buffer for printing the status information
* @buflen: Maximum length of the buffer
* Returns: Length of written status information or -1 on failure
*/
@@ -3282,6 +3739,17 @@ struct wpa_driver_ops {
int (*roaming)(void *priv, int allowed, const u8 *bssid);
/**
+ * disable_fils - Enable/disable FILS feature
+ * @priv: Private driver interface data
+ * @disable: 0-enable and 1-disable FILS feature
+ * Returns: 0 on success, -1 on failure
+ *
+ * This callback can be used to configure driver and below layers to
+ * enable/disable all FILS features.
+ */
+ int (*disable_fils)(void *priv, int disable);
+
+ /**
* set_mac_addr - Set MAC address
* @priv: Private driver interface data
* @addr: MAC address to use or %NULL for setting back to permanent
@@ -3295,6 +3763,14 @@ struct wpa_driver_ops {
int (*macsec_deinit)(void *priv);
/**
+ * macsec_get_capability - Inform MKA of this driver's capability
+ * @priv: Private driver interface data
+ * @cap: Driver's capability
+ * Returns: 0 on success, -1 on failure
+ */
+ int (*macsec_get_capability)(void *priv, enum macsec_cap *cap);
+
+ /**
* enable_protect_frames - Set protect frames status
* @priv: Private driver interface data
* @enabled: TRUE = protect frames enabled
@@ -3304,6 +3780,15 @@ struct wpa_driver_ops {
int (*enable_protect_frames)(void *priv, Boolean enabled);
/**
+ * enable_encrypt - Set encryption status
+ * @priv: Private driver interface data
+ * @enabled: TRUE = encrypt outgoing traffic
+ * FALSE = integrity-only protection on outgoing traffic
+ * Returns: 0 on success, -1 on failure (or if not supported)
+ */
+ int (*enable_encrypt)(void *priv, Boolean enabled);
+
+ /**
* set_replay_protect - Set replay protect status and window size
* @priv: Private driver interface data
* @enabled: TRUE = replay protect enabled
@@ -3333,155 +3818,137 @@ struct wpa_driver_ops {
/**
* get_receive_lowest_pn - Get receive lowest pn
* @priv: Private driver interface data
- * @channel: secure channel
- * @an: association number
- * @lowest_pn: lowest accept pn
+ * @sa: secure association
* Returns: 0 on success, -1 on failure (or if not supported)
*/
- int (*get_receive_lowest_pn)(void *priv, u32 channel, u8 an,
- u32 *lowest_pn);
+ int (*get_receive_lowest_pn)(void *priv, struct receive_sa *sa);
/**
* get_transmit_next_pn - Get transmit next pn
* @priv: Private driver interface data
- * @channel: secure channel
- * @an: association number
- * @next_pn: next pn
+ * @sa: secure association
* Returns: 0 on success, -1 on failure (or if not supported)
*/
- int (*get_transmit_next_pn)(void *priv, u32 channel, u8 an,
- u32 *next_pn);
+ int (*get_transmit_next_pn)(void *priv, struct transmit_sa *sa);
/**
* set_transmit_next_pn - Set transmit next pn
* @priv: Private driver interface data
- * @channel: secure channel
- * @an: association number
- * @next_pn: next pn
+ * @sa: secure association
* Returns: 0 on success, -1 on failure (or if not supported)
*/
- int (*set_transmit_next_pn)(void *priv, u32 channel, u8 an,
- u32 next_pn);
+ int (*set_transmit_next_pn)(void *priv, struct transmit_sa *sa);
/**
- * get_available_receive_sc - get available receive channel
+ * set_receive_lowest_pn - Set receive lowest PN
* @priv: Private driver interface data
- * @channel: secure channel
+ * @sa: secure association
* Returns: 0 on success, -1 on failure (or if not supported)
*/
- int (*get_available_receive_sc)(void *priv, u32 *channel);
+ int (*set_receive_lowest_pn)(void *priv, struct receive_sa *sa);
/**
* create_receive_sc - create secure channel for receiving
* @priv: Private driver interface data
- * @channel: secure channel
- * @sci_addr: secure channel identifier - address
- * @sci_port: secure channel identifier - port
+ * @sc: secure channel
* @conf_offset: confidentiality offset (0, 30, or 50)
* @validation: frame validation policy (0 = Disabled, 1 = Checked,
* 2 = Strict)
* Returns: 0 on success, -1 on failure (or if not supported)
*/
- int (*create_receive_sc)(void *priv, u32 channel, const u8 *sci_addr,
- u16 sci_port, unsigned int conf_offset,
+ int (*create_receive_sc)(void *priv, struct receive_sc *sc,
+ unsigned int conf_offset,
int validation);
/**
* delete_receive_sc - delete secure connection for receiving
* @priv: private driver interface data from init()
- * @channel: secure channel
+ * @sc: secure channel
* Returns: 0 on success, -1 on failure
*/
- int (*delete_receive_sc)(void *priv, u32 channel);
+ int (*delete_receive_sc)(void *priv, struct receive_sc *sc);
/**
* create_receive_sa - create secure association for receive
* @priv: private driver interface data from init()
- * @channel: secure channel
- * @an: association number
- * @lowest_pn: the lowest packet number can be received
- * @sak: the secure association key
+ * @sa: secure association
* Returns: 0 on success, -1 on failure
*/
- int (*create_receive_sa)(void *priv, u32 channel, u8 an,
- u32 lowest_pn, const u8 *sak);
+ int (*create_receive_sa)(void *priv, struct receive_sa *sa);
/**
- * enable_receive_sa - enable the SA for receive
- * @priv: private driver interface data from init()
- * @channel: secure channel
- * @an: association number
+ * delete_receive_sa - Delete secure association for receive
+ * @priv: Private driver interface data from init()
+ * @sa: Secure association
* Returns: 0 on success, -1 on failure
*/
- int (*enable_receive_sa)(void *priv, u32 channel, u8 an);
+ int (*delete_receive_sa)(void *priv, struct receive_sa *sa);
/**
- * disable_receive_sa - disable SA for receive
+ * enable_receive_sa - enable the SA for receive
* @priv: private driver interface data from init()
- * @channel: secure channel index
- * @an: association number
+ * @sa: secure association
* Returns: 0 on success, -1 on failure
*/
- int (*disable_receive_sa)(void *priv, u32 channel, u8 an);
+ int (*enable_receive_sa)(void *priv, struct receive_sa *sa);
/**
- * get_available_transmit_sc - get available transmit channel
- * @priv: Private driver interface data
- * @channel: secure channel
- * Returns: 0 on success, -1 on failure (or if not supported)
+ * disable_receive_sa - disable SA for receive
+ * @priv: private driver interface data from init()
+ * @sa: secure association
+ * Returns: 0 on success, -1 on failure
*/
- int (*get_available_transmit_sc)(void *priv, u32 *channel);
+ int (*disable_receive_sa)(void *priv, struct receive_sa *sa);
/**
* create_transmit_sc - create secure connection for transmit
* @priv: private driver interface data from init()
- * @channel: secure channel
- * @sci_addr: secure channel identifier - address
- * @sci_port: secure channel identifier - port
+ * @sc: secure channel
+ * @conf_offset: confidentiality offset (0, 30, or 50)
* Returns: 0 on success, -1 on failure
*/
- int (*create_transmit_sc)(void *priv, u32 channel, const u8 *sci_addr,
- u16 sci_port, unsigned int conf_offset);
+ int (*create_transmit_sc)(void *priv, struct transmit_sc *sc,
+ unsigned int conf_offset);
/**
* delete_transmit_sc - delete secure connection for transmit
* @priv: private driver interface data from init()
- * @channel: secure channel
+ * @sc: secure channel
* Returns: 0 on success, -1 on failure
*/
- int (*delete_transmit_sc)(void *priv, u32 channel);
+ int (*delete_transmit_sc)(void *priv, struct transmit_sc *sc);
/**
* create_transmit_sa - create secure association for transmit
* @priv: private driver interface data from init()
- * @channel: secure channel index
- * @an: association number
- * @next_pn: the packet number used as next transmit packet
- * @confidentiality: True if the SA is to provide confidentiality
- * as well as integrity
- * @sak: the secure association key
+ * @sa: secure association
* Returns: 0 on success, -1 on failure
*/
- int (*create_transmit_sa)(void *priv, u32 channel, u8 an, u32 next_pn,
- Boolean confidentiality, const u8 *sak);
+ int (*create_transmit_sa)(void *priv, struct transmit_sa *sa);
+
+ /**
+ * delete_transmit_sa - Delete secure association for transmit
+ * @priv: Private driver interface data from init()
+ * @sa: Secure association
+ * Returns: 0 on success, -1 on failure
+ */
+ int (*delete_transmit_sa)(void *priv, struct transmit_sa *sa);
/**
* enable_transmit_sa - enable SA for transmit
* @priv: private driver interface data from init()
- * @channel: secure channel
- * @an: association number
+ * @sa: secure association
* Returns: 0 on success, -1 on failure
*/
- int (*enable_transmit_sa)(void *priv, u32 channel, u8 an);
+ int (*enable_transmit_sa)(void *priv, struct transmit_sa *sa);
/**
* disable_transmit_sa - disable SA for transmit
* @priv: private driver interface data from init()
- * @channel: secure channel
- * @an: association number
+ * @sa: secure association
* Returns: 0 on success, -1 on failure
*/
- int (*disable_transmit_sa)(void *priv, u32 channel, u8 an);
+ int (*disable_transmit_sa)(void *priv, struct transmit_sa *sa);
#endif /* CONFIG_MACSEC */
/**
@@ -3555,9 +4022,12 @@ struct wpa_driver_ops {
/**
* abort_scan - Request the driver to abort an ongoing scan
* @priv: Private driver interface data
+ * @scan_cookie: Cookie identifying the scan request. This is used only
+ * when the vendor interface QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
+ * was used to trigger scan. Otherwise, 0 is used.
* Returns 0 on success, -1 on failure
*/
- int (*abort_scan)(void *priv);
+ int (*abort_scan)(void *priv, u64 scan_cookie);
/**
* configure_data_frame_filters - Request to configure frame filters
@@ -3623,8 +4093,81 @@ struct wpa_driver_ops {
*/
int (*set_default_scan_ies)(void *priv, const u8 *ies, size_t ies_len);
-};
+ /**
+ * set_tdls_mode - Set TDLS trigger mode to the host driver
+ * @priv: Private driver interface data
+ * @tdls_external_control: Represents if TDLS external trigger control
+ * mode is enabled/disabled.
+ *
+ * This optional callback can be used to configure the TDLS external
+ * trigger control mode to the host driver.
+ */
+ int (*set_tdls_mode)(void *priv, int tdls_external_control);
+ /**
+ * get_bss_transition_status - Get candidate BSS's transition status
+ * @priv: Private driver interface data
+ * @params: Candidate BSS list
+ *
+ * Get the accept or reject reason code for a list of BSS transition
+ * candidates.
+ */
+ struct wpa_bss_candidate_info *
+ (*get_bss_transition_status)(void *priv,
+ struct wpa_bss_trans_info *params);
+ /**
+ * ignore_assoc_disallow - Configure driver to ignore assoc_disallow
+ * @priv: Private driver interface data
+ * @ignore_disallow: 0 to not ignore, 1 to ignore
+ * Returns: 0 on success, -1 on failure
+ */
+ int (*ignore_assoc_disallow)(void *priv, int ignore_disallow);
+
+ /**
+ * set_bssid_blacklist - Set blacklist of BSSIDs to the driver
+ * @priv: Private driver interface data
+ * @num_bssid: Number of blacklist BSSIDs
+ * @bssids: List of blacklisted BSSIDs
+ */
+ int (*set_bssid_blacklist)(void *priv, unsigned int num_bssid,
+ const u8 *bssid);
+
+ /**
+ * update_connect_params - Update the connection parameters
+ * @priv: Private driver interface data
+ * @params: Association parameters
+ * @mask: Bit mask indicating which parameters in @params have to be
+ * updated
+ * Returns: 0 on success, -1 on failure
+ *
+ * Update the connection parameters when in connected state so that the
+ * driver uses the updated parameters for subsequent roaming. This is
+ * used only with drivers that implement internal BSS selection and
+ * roaming.
+ */
+ int (*update_connect_params)(
+ void *priv, struct wpa_driver_associate_params *params,
+ enum wpa_drv_update_connect_params_mask mask);
+
+ /**
+ * send_external_auth_status - Indicate the status of external
+ * authentication processing to the host driver.
+ * @priv: Private driver interface data
+ * @params: Status of authentication processing.
+ * Returns: 0 on success, -1 on failure
+ */
+ int (*send_external_auth_status)(void *priv,
+ struct external_auth *params);
+
+ /**
+ * set_4addr_mode - Set 4-address mode
+ * @priv: Private driver interface data
+ * @bridge_ifname: Bridge interface name
+ * @val: 0 - disable 4addr mode, 1 - enable 4addr mode
+ * Returns: 0 on success, < 0 on failure
+ */
+ int (*set_4addr_mode)(void *priv, const char *bridge_ifname, int val);
+};
/**
* enum wpa_event_type - Event type for wpa_supplicant_event() calls
@@ -3734,17 +4277,6 @@ enum wpa_event_type {
EVENT_PMKID_CANDIDATE,
/**
- * EVENT_STKSTART - Request STK handshake (MLME-STKSTART.request)
- *
- * This event can be used to inform wpa_supplicant about desire to set
- * up secure direct link connection between two stations as defined in
- * IEEE 802.11e with a new PeerKey mechanism that replaced the original
- * STAKey negotiation. The caller will need to set peer address for the
- * event.
- */
- EVENT_STKSTART,
-
- /**
* EVENT_TDLS - Request TDLS operation
*
* This event can be used to request a TDLS operation to be performed.
@@ -4043,7 +4575,7 @@ enum wpa_event_type {
* EVENT_DFS_CAC_ABORTED - Notify that channel availability check has been aborted
*
* The CAC was not successful, and the channel remains in the previous
- * state. This may happen due to a radar beeing detected or other
+ * state. This may happen due to a radar being detected or other
* external influences.
*/
EVENT_DFS_CAC_ABORTED,
@@ -4112,6 +4644,65 @@ enum wpa_event_type {
* EVENT_P2P_LO_STOP - Notify that P2P listen offload is stopped
*/
EVENT_P2P_LO_STOP,
+
+ /**
+ * EVENT_BEACON_LOSS - Beacon loss detected
+ *
+ * This event indicates that no Beacon frames has been received from
+ * the current AP. This may indicate that the AP is not anymore in
+ * range.
+ */
+ EVENT_BEACON_LOSS,
+
+ /**
+ * EVENT_DFS_PRE_CAC_EXPIRED - Notify that channel availability check
+ * done previously (Pre-CAC) on the channel has expired. This would
+ * normally be on a non-ETSI DFS regulatory domain. DFS state of the
+ * channel will be moved from available to usable. A new CAC has to be
+ * performed before start operating on this channel.
+ */
+ EVENT_DFS_PRE_CAC_EXPIRED,
+
+ /**
+ * EVENT_EXTERNAL_AUTH - This event interface is used by host drivers
+ * that do not define separate commands for authentication and
+ * association (~WPA_DRIVER_FLAGS_SME) but offload the 802.11
+ * authentication to wpa_supplicant. This event carries all the
+ * necessary information from the host driver for the authentication to
+ * happen.
+ */
+ EVENT_EXTERNAL_AUTH,
+
+ /**
+ * EVENT_PORT_AUTHORIZED - Notification that a connection is authorized
+ *
+ * This event should be indicated when the driver completes the 4-way
+ * handshake. This event should be preceded by an EVENT_ASSOC that
+ * indicates the completion of IEEE 802.11 association.
+ */
+ EVENT_PORT_AUTHORIZED,
+
+ /**
+ * EVENT_STATION_OPMODE_CHANGED - Notify STA's HT/VHT operation mode
+ * change event.
+ */
+ EVENT_STATION_OPMODE_CHANGED,
+
+ /**
+ * EVENT_INTERFACE_MAC_CHANGED - Notify that interface MAC changed
+ *
+ * This event is emitted when the MAC changes while the interface is
+ * enabled. When an interface was disabled and becomes enabled, it
+ * must be always assumed that the MAC possibly changed.
+ */
+ EVENT_INTERFACE_MAC_CHANGED,
+
+ /**
+ * EVENT_WDS_STA_INTERFACE_STATUS - Notify WDS STA interface status
+ *
+ * This event is emitted when an interface is added/removed for WDS STA.
+ */
+ EVENT_WDS_STA_INTERFACE_STATUS,
};
@@ -4204,6 +4795,16 @@ union wpa_event_data {
size_t resp_ies_len;
/**
+ * resp_frame - (Re)Association Response frame
+ */
+ const u8 *resp_frame;
+
+ /**
+ * resp_frame_len - (Re)Association Response frame length
+ */
+ size_t resp_frame_len;
+
+ /**
* beacon_ies - Beacon or Probe Response IEs
*
* Optional Beacon/ProbeResp data: IEs included in Beacon or
@@ -4280,6 +4881,8 @@ union wpa_event_data {
/**
* ptk_kek - The derived PTK KEK
+ * This is used in key management offload and also in FILS SK
+ * offload.
*/
const u8 *ptk_kek;
@@ -4293,6 +4896,36 @@ union wpa_event_data {
* 0 = unknown, 1 = unchanged, 2 = changed
*/
u8 subnet_status;
+
+ /**
+ * The following information is used in FILS SK offload
+ * @fils_erp_next_seq_num
+ * @fils_pmk
+ * @fils_pmk_len
+ * @fils_pmkid
+ */
+
+ /**
+ * fils_erp_next_seq_num - The next sequence number to use in
+ * FILS ERP messages
+ */
+ u16 fils_erp_next_seq_num;
+
+ /**
+ * fils_pmk - A new PMK if generated in case of FILS
+ * authentication
+ */
+ const u8 *fils_pmk;
+
+ /**
+ * fils_pmk_len - Length of fils_pmk
+ */
+ size_t fils_pmk_len;
+
+ /**
+ * fils_pmkid - PMKID used or generated in FILS authentication
+ */
+ const u8 *fils_pmkid;
} assoc_info;
/**
@@ -4389,13 +5022,6 @@ union wpa_event_data {
} pmkid_candidate;
/**
- * struct stkstart - Data for EVENT_STKSTART
- */
- struct stkstart {
- u8 peer[ETH_ALEN];
- } stkstart;
-
- /**
* struct tdls - Data for EVENT_TDLS
*/
struct tdls {
@@ -4503,6 +5129,17 @@ union wpa_event_data {
* than explicit rejection response from the AP.
*/
int timed_out;
+
+ /**
+ * timeout_reason - Reason for the timeout
+ */
+ const char *timeout_reason;
+
+ /**
+ * fils_erp_next_seq_num - The next sequence number to use in
+ * FILS ERP messages
+ */
+ u16 fils_erp_next_seq_num;
} assoc_reject;
struct timeout_event {
@@ -4586,6 +5223,11 @@ union wpa_event_data {
* @external_scan: Whether the scan info is for an external scan
* @nl_scan_event: 1 if the source of this scan event is a normal scan,
* 0 if the source of the scan event is a vendor scan
+ * @scan_start_tsf: Time when the scan started in terms of TSF of the
+ * BSS that the interface that requested the scan is connected to
+ * (if available).
+ * @scan_start_tsf_bssid: The BSSID according to which %scan_start_tsf
+ * is set.
*/
struct scan_info {
int aborted;
@@ -4595,6 +5237,8 @@ union wpa_event_data {
size_t num_ssids;
int external_scan;
int nl_scan_event;
+ u64 scan_start_tsf;
+ u8 scan_start_tsf_bssid[ETH_ALEN];
} scan_info;
/**
@@ -4684,9 +5328,12 @@ union wpa_event_data {
/**
* struct low_ack - Data for EVENT_STATION_LOW_ACK events
* @addr: station address
+ * @num_packets: Number of packets lost (consecutive packets not
+ * acknowledged)
*/
struct low_ack {
u8 addr[ETH_ALEN];
+ u32 num_packets;
} low_ack;
/**
@@ -4858,6 +5505,37 @@ union wpa_event_data {
P2P_LO_STOPPED_REASON_NOT_SUPPORTED,
} reason_code;
} p2p_lo_stop;
+
+ /* For EVENT_EXTERNAL_AUTH */
+ struct external_auth external_auth;
+
+ /**
+ * struct sta_opmode - Station's operation mode change event
+ * @addr: The station MAC address
+ * @smps_mode: SMPS mode of the station
+ * @chan_width: Channel width of the station
+ * @rx_nss: RX_NSS of the station
+ *
+ * This is used as data with EVENT_STATION_OPMODE_CHANGED.
+ */
+ struct sta_opmode {
+ const u8 *addr;
+ enum smps_mode smps_mode;
+ enum chan_width chan_width;
+ u8 rx_nss;
+ } sta_opmode;
+
+ /**
+ * struct wds_sta_interface - Data for EVENT_WDS_STA_INTERFACE_STATUS.
+ */
+ struct wds_sta_interface {
+ const u8 *sta_addr;
+ const char *ifname;
+ enum {
+ INTERFACE_ADDED,
+ INTERFACE_REMOVED
+ } istatus;
+ } wds_sta_interface;
};
/**
@@ -4931,6 +5609,8 @@ const char * event_to_string(enum wpa_event_type event);
/* Convert chan_width to a string for logging and control interfaces */
const char * channel_width_to_string(enum chan_width width);
+int channel_width_to_int(enum chan_width width);
+
int ht_supported(const struct hostapd_hw_modes *mode);
int vht_supported(const struct hostapd_hw_modes *mode);
@@ -4973,6 +5653,10 @@ extern const struct wpa_driver_ops wpa_driver_wired_ops; /* driver_wired.c */
/* driver_macsec_qca.c */
extern const struct wpa_driver_ops wpa_driver_macsec_qca_ops;
#endif /* CONFIG_DRIVER_MACSEC_QCA */
+#ifdef CONFIG_DRIVER_MACSEC_LINUX
+/* driver_macsec_linux.c */
+extern const struct wpa_driver_ops wpa_driver_macsec_linux_ops;
+#endif /* CONFIG_DRIVER_MACSEC_LINUX */
#ifdef CONFIG_DRIVER_ROBOSWITCH
/* driver_roboswitch.c */
extern const struct wpa_driver_ops wpa_driver_roboswitch_ops;
diff --git a/freebsd/contrib/wpa/src/drivers/driver_bsd.c b/freebsd/contrib/wpa/src/drivers/driver_bsd.c
index c1679806..3ef49fd7 100644
--- a/freebsd/contrib/wpa/src/drivers/driver_bsd.c
+++ b/freebsd/contrib/wpa/src/drivers/driver_bsd.c
@@ -144,7 +144,7 @@ bsd_get80211(void *priv, struct ieee80211req *ireq, int op, void *arg,
ireq->i_data = arg;
if (ioctl(drv->global->sock, SIOCG80211, ireq) < 0) {
- wpa_printf(MSG_ERROR, "ioctl[SIOCS80211, op=%u, "
+ wpa_printf(MSG_ERROR, "ioctl[SIOCG80211, op=%u, "
"arg_len=%u]: %s", op, arg_len, strerror(errno));
return -1;
}
diff --git a/freebsd/contrib/wpa/src/drivers/driver_common.c b/freebsd/contrib/wpa/src/drivers/driver_common.c
index 139829e4..be9ff3f6 100644
--- a/freebsd/contrib/wpa/src/drivers/driver_common.c
+++ b/freebsd/contrib/wpa/src/drivers/driver_common.c
@@ -2,7 +2,7 @@
/*
* Common driver-related functions
- * Copyright (c) 2003-2011, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2017, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -37,7 +37,6 @@ const char * event_to_string(enum wpa_event_type event)
E2S(ASSOCINFO);
E2S(INTERFACE_STATUS);
E2S(PMKID_CANDIDATE);
- E2S(STKSTART);
E2S(TDLS);
E2S(FT_RESPONSE);
E2S(IBSS_RSN_START);
@@ -83,6 +82,13 @@ const char * event_to_string(enum wpa_event_type event)
E2S(ACS_CHANNEL_SELECTED);
E2S(DFS_CAC_STARTED);
E2S(P2P_LO_STOP);
+ E2S(BEACON_LOSS);
+ E2S(DFS_PRE_CAC_EXPIRED);
+ E2S(EXTERNAL_AUTH);
+ E2S(PORT_AUTHORIZED);
+ E2S(STATION_OPMODE_CHANGED);
+ E2S(INTERFACE_MAC_CHANGED);
+ E2S(WDS_STA_INTERFACE_STATUS);
}
return "UNKNOWN";
@@ -111,6 +117,25 @@ const char * channel_width_to_string(enum chan_width width)
}
+int channel_width_to_int(enum chan_width width)
+{
+ switch (width) {
+ case CHAN_WIDTH_20_NOHT:
+ case CHAN_WIDTH_20:
+ return 20;
+ case CHAN_WIDTH_40:
+ return 40;
+ case CHAN_WIDTH_80:
+ return 80;
+ case CHAN_WIDTH_80P80:
+ case CHAN_WIDTH_160:
+ return 160;
+ default:
+ return 0;
+ }
+}
+
+
int ht_supported(const struct hostapd_hw_modes *mode)
{
if (!(mode->flags & HOSTAPD_MODE_FLAG_HT_INFO_KNOWN)) {
@@ -230,7 +255,8 @@ const char * driver_flag_to_string(u64 flag)
DF2S(DRIVER_IE);
DF2S(SET_KEYS_AFTER_ASSOC);
DF2S(DFS_OFFLOAD);
- DF2S(4WAY_HANDSHAKE);
+ DF2S(4WAY_HANDSHAKE_PSK);
+ DF2S(4WAY_HANDSHAKE_8021X);
DF2S(WIRED);
DF2S(SME);
DF2S(AP);
@@ -269,6 +295,19 @@ const char * driver_flag_to_string(u64 flag)
DF2S(OFFCHANNEL_SIMULTANEOUS);
DF2S(FULL_AP_CLIENT_STATE);
DF2S(P2P_LISTEN_OFFLOAD);
+ DF2S(SUPPORT_FILS);
+ DF2S(BEACON_RATE_LEGACY);
+ DF2S(BEACON_RATE_HT);
+ DF2S(BEACON_RATE_VHT);
+ DF2S(MGMT_TX_RANDOM_TA);
+ DF2S(MGMT_TX_RANDOM_TA_CONNECTED);
+ DF2S(SCHED_SCAN_RELATIVE_RSSI);
+ DF2S(HE_CAPABILITIES);
+ DF2S(FILS_SK_OFFLOAD);
+ DF2S(OCE_STA);
+ DF2S(OCE_AP);
+ DF2S(OCE_STA_CFON);
+ DF2S(MFP_OPTIONAL);
}
return "UNKNOWN";
#undef DF2S
diff --git a/freebsd/contrib/wpa/src/drivers/driver_ndis.c b/freebsd/contrib/wpa/src/drivers/driver_ndis.c
index 98aa48ba..7e0db265 100644
--- a/freebsd/contrib/wpa/src/drivers/driver_ndis.c
+++ b/freebsd/contrib/wpa/src/drivers/driver_ndis.c
@@ -1223,12 +1223,16 @@ static int wpa_driver_ndis_set_pmkid(struct wpa_driver_ndis_data *drv)
}
-static int wpa_driver_ndis_add_pmkid(void *priv, const u8 *bssid,
- const u8 *pmkid)
+static int wpa_driver_ndis_add_pmkid(void *priv,
+ struct wpa_pmkid_params *params)
{
struct wpa_driver_ndis_data *drv = priv;
struct ndis_pmkid_entry *entry, *prev;
+ const u8 *bssid = params->bssid;
+ const u8 *pmkid = params->pmkid;
+ if (!bssid || !pmkid)
+ return -1;
if (drv->no_of_pmkid == 0)
return 0;
@@ -1264,12 +1268,16 @@ static int wpa_driver_ndis_add_pmkid(void *priv, const u8 *bssid,
}
-static int wpa_driver_ndis_remove_pmkid(void *priv, const u8 *bssid,
- const u8 *pmkid)
+static int wpa_driver_ndis_remove_pmkid(void *priv,
+ struct wpa_pmkid_params *params)
{
struct wpa_driver_ndis_data *drv = priv;
struct ndis_pmkid_entry *entry, *prev;
+ const u8 *bssid = params->bssid;
+ const u8 *pmkid = params->pmkid;
+ if (!bssid || !pmkid)
+ return -1;
if (drv->no_of_pmkid == 0)
return 0;
diff --git a/freebsd/contrib/wpa/src/drivers/driver_nl80211.h b/freebsd/contrib/wpa/src/drivers/driver_nl80211.h
index d0ec48c9..1e7fe7a9 100644
--- a/freebsd/contrib/wpa/src/drivers/driver_nl80211.h
+++ b/freebsd/contrib/wpa/src/drivers/driver_nl80211.h
@@ -60,11 +60,13 @@ struct i802_bss {
char brname[IFNAMSIZ];
unsigned int beacon_set:1;
unsigned int added_if_into_bridge:1;
+ unsigned int already_in_bridge:1;
unsigned int added_bridge:1;
unsigned int in_deinit:1;
unsigned int wdev_id_set:1;
unsigned int added_if:1;
unsigned int static_ap:1;
+ unsigned int use_nl_connect:1;
u8 addr[ETH_ALEN];
@@ -73,11 +75,12 @@ struct i802_bss {
int if_dynamic;
void *ctx;
- struct nl_handle *nl_preq, *nl_mgmt;
+ struct nl_handle *nl_preq, *nl_mgmt, *nl_connect;
struct nl_cb *nl_cb;
struct nl80211_wiphy_data *wiphy_data;
struct dl_list wiphy_list;
+ u8 rand_addr[ETH_ALEN];
};
struct wpa_driver_nl80211_data {
@@ -160,6 +163,10 @@ struct wpa_driver_nl80211_data {
unsigned int scan_vendor_cmd_avail:1;
unsigned int connect_reassoc:1;
unsigned int set_wifi_conf_vendor_cmd_avail:1;
+ unsigned int he_capab_vendor_cmd_avail:1;
+ unsigned int fetch_bss_trans_status:1;
+ unsigned int roam_vendor_cmd_avail:1;
+ unsigned int get_supported_akm_suites_avail:1;
u64 vendor_scan_cookie;
u64 remain_on_chan_cookie;
@@ -208,6 +215,8 @@ struct wpa_driver_nl80211_data {
* (NL80211_CMD_VENDOR). 0 if no pending scan request.
*/
int last_scan_cmd;
+
+ struct he_capabilities he_capab;
};
struct nl_msg;
@@ -228,6 +237,7 @@ int nl80211_create_iface(struct wpa_driver_nl80211_data *drv,
void *arg, int use_existing);
void nl80211_remove_iface(struct wpa_driver_nl80211_data *drv, int ifidx);
unsigned int nl80211_get_assoc_freq(struct wpa_driver_nl80211_data *drv);
+int nl80211_get_assoc_ssid(struct wpa_driver_nl80211_data *drv, u8 *ssid);
enum chan_width convert2width(int width);
void nl80211_mark_disconnected(struct wpa_driver_nl80211_data *drv);
struct i802_bss * get_bss_ifindex(struct wpa_driver_nl80211_data *drv,
@@ -244,7 +254,8 @@ int wpa_driver_nl80211_set_mode(struct i802_bss *bss,
enum nl80211_iftype nlmode);
int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
const u8 *addr, int cmd, u16 reason_code,
- int local_state_change);
+ int local_state_change,
+ struct nl_handle *nl_connect);
int nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv);
void nl80211_remove_monitor_interface(struct wpa_driver_nl80211_data *drv);
@@ -254,7 +265,8 @@ int nl80211_send_monitor(struct wpa_driver_nl80211_data *drv,
int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv);
struct hostapd_hw_modes *
-nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags);
+nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags,
+ u8 *dfs_domain);
int process_global_event(struct nl_msg *msg, void *arg);
int process_bss_event(struct nl_msg *msg, void *arg);
@@ -282,15 +294,6 @@ int wpa_driver_set_ap_wps_p2p_ie(void *priv, const struct wpabuf *beacon,
/* driver_nl80211_scan.c */
-struct nl80211_bss_info_arg {
- struct wpa_driver_nl80211_data *drv;
- struct wpa_scan_results *res;
- unsigned int assoc_freq;
- unsigned int ibss_freq;
- u8 assoc_bssid[ETH_ALEN];
-};
-
-int bss_info_handler(struct nl_msg *msg, void *arg);
void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx);
int wpa_driver_nl80211_scan(struct i802_bss *bss,
struct wpa_driver_scan_params *params);
@@ -299,7 +302,7 @@ int wpa_driver_nl80211_sched_scan(void *priv,
int wpa_driver_nl80211_stop_sched_scan(void *priv);
struct wpa_scan_results * wpa_driver_nl80211_get_scan_results(void *priv);
void nl80211_dump_scan(struct wpa_driver_nl80211_data *drv);
-int wpa_driver_nl80211_abort_scan(void *priv);
+int wpa_driver_nl80211_abort_scan(void *priv, u64 scan_cookie);
int wpa_driver_nl80211_vendor_scan(struct i802_bss *bss,
struct wpa_driver_scan_params *params);
int nl80211_set_default_scan_ies(void *priv, const u8 *ies, size_t ies_len);
diff --git a/freebsd/contrib/wpa/src/drivers/driver_wired.c b/freebsd/contrib/wpa/src/drivers/driver_wired.c
index 372bf791..0972df92 100644
--- a/freebsd/contrib/wpa/src/drivers/driver_wired.c
+++ b/freebsd/contrib/wpa/src/drivers/driver_wired.c
@@ -14,6 +14,7 @@
#include "common.h"
#include "eloop.h"
#include "driver.h"
+#include "driver_wired_common.h"
#include <sys/ioctl.h>
#undef IFNAMSIZ
@@ -44,20 +45,12 @@ struct ieee8023_hdr {
#pragma pack(pop)
#endif /* _MSC_VER */
-static const u8 pae_group_addr[ETH_ALEN] =
-{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 };
-
struct wpa_driver_wired_data {
- char ifname[IFNAMSIZ + 1];
- void *ctx;
+ struct driver_wired_common_data common;
- int sock; /* raw packet socket for driver access */
int dhcp_sock; /* socket for dhcp packets */
int use_pae_group_addr;
-
- int pf_sock;
- int membership, multi, iff_allmulti, iff_up;
};
@@ -85,34 +78,6 @@ struct dhcp_message {
};
-static int wired_multicast_membership(int sock, int ifindex,
- const u8 *addr, int add)
-{
-#ifdef __linux__
- struct packet_mreq mreq;
-
- if (sock < 0)
- return -1;
-
- os_memset(&mreq, 0, sizeof(mreq));
- mreq.mr_ifindex = ifindex;
- mreq.mr_type = PACKET_MR_MULTICAST;
- mreq.mr_alen = ETH_ALEN;
- os_memcpy(mreq.mr_address, addr, ETH_ALEN);
-
- if (setsockopt(sock, SOL_PACKET,
- add ? PACKET_ADD_MEMBERSHIP : PACKET_DROP_MEMBERSHIP,
- &mreq, sizeof(mreq)) < 0) {
- wpa_printf(MSG_ERROR, "setsockopt: %s", strerror(errno));
- return -1;
- }
- return 0;
-#else /* __linux__ */
- return -1;
-#endif /* __linux__ */
-}
-
-
#ifdef __linux__
static void handle_data(void *ctx, unsigned char *buf, size_t len)
{
@@ -133,16 +98,16 @@ static void handle_data(void *ctx, unsigned char *buf, size_t len)
hdr = (struct ieee8023_hdr *) buf;
switch (ntohs(hdr->ethertype)) {
- case ETH_P_PAE:
- wpa_printf(MSG_MSGDUMP, "Received EAPOL packet");
- sa = hdr->src;
- os_memset(&event, 0, sizeof(event));
- event.new_sta.addr = sa;
- wpa_supplicant_event(ctx, EVENT_NEW_STA, &event);
-
- pos = (u8 *) (hdr + 1);
- left = len - sizeof(*hdr);
- drv_event_eapol_rx(ctx, sa, pos, left);
+ case ETH_P_PAE:
+ wpa_printf(MSG_MSGDUMP, "Received EAPOL packet");
+ sa = hdr->src;
+ os_memset(&event, 0, sizeof(event));
+ event.new_sta.addr = sa;
+ wpa_supplicant_event(ctx, EVENT_NEW_STA, &event);
+
+ pos = (u8 *) (hdr + 1);
+ left = len - sizeof(*hdr);
+ drv_event_eapol_rx(ctx, sa, pos, left);
break;
default:
@@ -210,21 +175,22 @@ static int wired_init_sockets(struct wpa_driver_wired_data *drv, u8 *own_addr)
struct sockaddr_in addr2;
int n = 1;
- drv->sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_PAE));
- if (drv->sock < 0) {
+ drv->common.sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_PAE));
+ if (drv->common.sock < 0) {
wpa_printf(MSG_ERROR, "socket[PF_PACKET,SOCK_RAW]: %s",
strerror(errno));
return -1;
}
- if (eloop_register_read_sock(drv->sock, handle_read, drv->ctx, NULL)) {
+ if (eloop_register_read_sock(drv->common.sock, handle_read,
+ drv->common.ctx, NULL)) {
wpa_printf(MSG_INFO, "Could not register read socket");
return -1;
}
os_memset(&ifr, 0, sizeof(ifr));
- os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
- if (ioctl(drv->sock, SIOCGIFINDEX, &ifr) != 0) {
+ os_strlcpy(ifr.ifr_name, drv->common.ifname, sizeof(ifr.ifr_name));
+ if (ioctl(drv->common.sock, SIOCGIFINDEX, &ifr) != 0) {
wpa_printf(MSG_ERROR, "ioctl(SIOCGIFINDEX): %s",
strerror(errno));
return -1;
@@ -236,13 +202,14 @@ static int wired_init_sockets(struct wpa_driver_wired_data *drv, u8 *own_addr)
wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d",
addr.sll_ifindex);
- if (bind(drv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ if (bind(drv->common.sock, (struct sockaddr *) &addr, sizeof(addr)) < 0)
+ {
wpa_printf(MSG_ERROR, "bind: %s", strerror(errno));
return -1;
}
/* filter multicast address */
- if (wired_multicast_membership(drv->sock, ifr.ifr_ifindex,
+ if (wired_multicast_membership(drv->common.sock, ifr.ifr_ifindex,
pae_group_addr, 1) < 0) {
wpa_printf(MSG_ERROR, "wired: Failed to add multicast group "
"membership");
@@ -250,8 +217,8 @@ static int wired_init_sockets(struct wpa_driver_wired_data *drv, u8 *own_addr)
}
os_memset(&ifr, 0, sizeof(ifr));
- os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
- if (ioctl(drv->sock, SIOCGIFHWADDR, &ifr) != 0) {
+ os_strlcpy(ifr.ifr_name, drv->common.ifname, sizeof(ifr.ifr_name));
+ if (ioctl(drv->common.sock, SIOCGIFHWADDR, &ifr) != 0) {
wpa_printf(MSG_ERROR, "ioctl(SIOCGIFHWADDR): %s",
strerror(errno));
return -1;
@@ -271,8 +238,8 @@ static int wired_init_sockets(struct wpa_driver_wired_data *drv, u8 *own_addr)
return -1;
}
- if (eloop_register_read_sock(drv->dhcp_sock, handle_dhcp, drv->ctx,
- NULL)) {
+ if (eloop_register_read_sock(drv->dhcp_sock, handle_dhcp,
+ drv->common.ctx, NULL)) {
wpa_printf(MSG_INFO, "Could not register read socket");
return -1;
}
@@ -296,7 +263,7 @@ static int wired_init_sockets(struct wpa_driver_wired_data *drv, u8 *own_addr)
}
os_memset(&ifr, 0, sizeof(ifr));
- os_strlcpy(ifr.ifr_ifrn.ifrn_name, drv->ifname, IFNAMSIZ);
+ os_strlcpy(ifr.ifr_ifrn.ifrn_name, drv->common.ifname, IFNAMSIZ);
if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_BINDTODEVICE,
(char *) &ifr, sizeof(ifr)) < 0) {
wpa_printf(MSG_ERROR,
@@ -345,7 +312,7 @@ static int wired_send_eapol(void *priv, const u8 *addr,
pos = (u8 *) (hdr + 1);
os_memcpy(pos, data, data_len);
- res = send(drv->sock, (u8 *) hdr, len, 0);
+ res = send(drv->common.sock, (u8 *) hdr, len, 0);
os_free(hdr);
if (res < 0) {
@@ -370,8 +337,9 @@ static void * wired_driver_hapd_init(struct hostapd_data *hapd,
return NULL;
}
- drv->ctx = hapd;
- os_strlcpy(drv->ifname, params->ifname, sizeof(drv->ifname));
+ drv->common.ctx = hapd;
+ os_strlcpy(drv->common.ifname, params->ifname,
+ sizeof(drv->common.ifname));
drv->use_pae_group_addr = params->use_pae_group_addr;
if (wired_init_sockets(drv, params->own_addr)) {
@@ -387,9 +355,9 @@ static void wired_driver_hapd_deinit(void *priv)
{
struct wpa_driver_wired_data *drv = priv;
- if (drv->sock >= 0) {
- eloop_unregister_read_sock(drv->sock);
- close(drv->sock);
+ if (drv->common.sock >= 0) {
+ eloop_unregister_read_sock(drv->common.sock);
+ close(drv->common.sock);
}
if (drv->dhcp_sock >= 0) {
@@ -401,227 +369,18 @@ static void wired_driver_hapd_deinit(void *priv)
}
-static int wpa_driver_wired_get_ssid(void *priv, u8 *ssid)
-{
- ssid[0] = 0;
- return 0;
-}
-
-
-static int wpa_driver_wired_get_bssid(void *priv, u8 *bssid)
-{
- /* Report PAE group address as the "BSSID" for wired connection. */
- os_memcpy(bssid, pae_group_addr, ETH_ALEN);
- return 0;
-}
-
-
-static int wpa_driver_wired_get_capa(void *priv, struct wpa_driver_capa *capa)
-{
- os_memset(capa, 0, sizeof(*capa));
- capa->flags = WPA_DRIVER_FLAGS_WIRED;
- return 0;
-}
-
-
-static int wpa_driver_wired_get_ifflags(const char *ifname, int *flags)
-{
- struct ifreq ifr;
- int s;
-
- s = socket(PF_INET, SOCK_DGRAM, 0);
- if (s < 0) {
- wpa_printf(MSG_ERROR, "socket: %s", strerror(errno));
- return -1;
- }
-
- os_memset(&ifr, 0, sizeof(ifr));
- os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
- if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
- wpa_printf(MSG_ERROR, "ioctl[SIOCGIFFLAGS]: %s",
- strerror(errno));
- close(s);
- return -1;
- }
- close(s);
- *flags = ifr.ifr_flags & 0xffff;
- return 0;
-}
-
-
-static int wpa_driver_wired_set_ifflags(const char *ifname, int flags)
-{
- struct ifreq ifr;
- int s;
-
- s = socket(PF_INET, SOCK_DGRAM, 0);
- if (s < 0) {
- wpa_printf(MSG_ERROR, "socket: %s", strerror(errno));
- return -1;
- }
-
- os_memset(&ifr, 0, sizeof(ifr));
- os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
- ifr.ifr_flags = flags & 0xffff;
- if (ioctl(s, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
- wpa_printf(MSG_ERROR, "ioctl[SIOCSIFFLAGS]: %s",
- strerror(errno));
- close(s);
- return -1;
- }
- close(s);
- return 0;
-}
-
-
-#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
-static int wpa_driver_wired_get_ifstatus(const char *ifname, int *status)
-{
- struct ifmediareq ifmr;
- int s;
-
- s = socket(PF_INET, SOCK_DGRAM, 0);
- if (s < 0) {
- wpa_printf(MSG_ERROR, "socket: %s", strerror(errno));
- return -1;
- }
-
- os_memset(&ifmr, 0, sizeof(ifmr));
- os_strlcpy(ifmr.ifm_name, ifname, IFNAMSIZ);
- if (ioctl(s, SIOCGIFMEDIA, (caddr_t) &ifmr) < 0) {
- wpa_printf(MSG_ERROR, "ioctl[SIOCGIFMEDIA]: %s",
- strerror(errno));
- close(s);
- return -1;
- }
- close(s);
- *status = (ifmr.ifm_status & (IFM_ACTIVE | IFM_AVALID)) ==
- (IFM_ACTIVE | IFM_AVALID);
-
- return 0;
-}
-#endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(FreeBSD_kernel__) */
-
-
-static int wpa_driver_wired_multi(const char *ifname, const u8 *addr, int add)
-{
- struct ifreq ifr;
- int s;
-
-#ifdef __sun__
- return -1;
-#endif /* __sun__ */
-
- s = socket(PF_INET, SOCK_DGRAM, 0);
- if (s < 0) {
- wpa_printf(MSG_ERROR, "socket: %s", strerror(errno));
- return -1;
- }
-
- os_memset(&ifr, 0, sizeof(ifr));
- os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
-#ifdef __linux__
- ifr.ifr_hwaddr.sa_family = AF_UNSPEC;
- os_memcpy(ifr.ifr_hwaddr.sa_data, addr, ETH_ALEN);
-#endif /* __linux__ */
-#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
- {
- struct sockaddr_dl *dlp;
- dlp = (struct sockaddr_dl *) &ifr.ifr_addr;
- dlp->sdl_len = sizeof(struct sockaddr_dl);
- dlp->sdl_family = AF_LINK;
- dlp->sdl_index = 0;
- dlp->sdl_nlen = 0;
- dlp->sdl_alen = ETH_ALEN;
- dlp->sdl_slen = 0;
- os_memcpy(LLADDR(dlp), addr, ETH_ALEN);
- }
-#endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(FreeBSD_kernel__) */
-#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
- {
- struct sockaddr *sap;
- sap = (struct sockaddr *) &ifr.ifr_addr;
- sap->sa_len = sizeof(struct sockaddr);
- sap->sa_family = AF_UNSPEC;
- os_memcpy(sap->sa_data, addr, ETH_ALEN);
- }
-#endif /* defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__) */
-
- if (ioctl(s, add ? SIOCADDMULTI : SIOCDELMULTI, (caddr_t) &ifr) < 0) {
- wpa_printf(MSG_ERROR, "ioctl[SIOC{ADD/DEL}MULTI]: %s",
- strerror(errno));
- close(s);
- return -1;
- }
- close(s);
- return 0;
-}
-
-
static void * wpa_driver_wired_init(void *ctx, const char *ifname)
{
struct wpa_driver_wired_data *drv;
- int flags;
drv = os_zalloc(sizeof(*drv));
if (drv == NULL)
return NULL;
- os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
- drv->ctx = ctx;
-
-#ifdef __linux__
- drv->pf_sock = socket(PF_PACKET, SOCK_DGRAM, 0);
- if (drv->pf_sock < 0)
- wpa_printf(MSG_ERROR, "socket(PF_PACKET): %s", strerror(errno));
-#else /* __linux__ */
- drv->pf_sock = -1;
-#endif /* __linux__ */
- if (wpa_driver_wired_get_ifflags(ifname, &flags) == 0 &&
- !(flags & IFF_UP) &&
- wpa_driver_wired_set_ifflags(ifname, flags | IFF_UP) == 0) {
- drv->iff_up = 1;
- }
-
- if (wired_multicast_membership(drv->pf_sock,
- if_nametoindex(drv->ifname),
- pae_group_addr, 1) == 0) {
- wpa_printf(MSG_DEBUG, "%s: Added multicast membership with "
- "packet socket", __func__);
- drv->membership = 1;
- } else if (wpa_driver_wired_multi(ifname, pae_group_addr, 1) == 0) {
- wpa_printf(MSG_DEBUG, "%s: Added multicast membership with "
- "SIOCADDMULTI", __func__);
- drv->multi = 1;
- } else if (wpa_driver_wired_get_ifflags(ifname, &flags) < 0) {
- wpa_printf(MSG_INFO, "%s: Could not get interface "
- "flags", __func__);
- os_free(drv);
- return NULL;
- } else if (flags & IFF_ALLMULTI) {
- wpa_printf(MSG_DEBUG, "%s: Interface is already configured "
- "for multicast", __func__);
- } else if (wpa_driver_wired_set_ifflags(ifname,
- flags | IFF_ALLMULTI) < 0) {
- wpa_printf(MSG_INFO, "%s: Failed to enable allmulti",
- __func__);
+ if (driver_wired_init_common(&drv->common, ifname, ctx) < 0) {
os_free(drv);
return NULL;
- } else {
- wpa_printf(MSG_DEBUG, "%s: Enabled allmulti mode",
- __func__);
- drv->iff_allmulti = 1;
}
-#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
- {
- int status;
- wpa_printf(MSG_DEBUG, "%s: waiting for link to become active",
- __func__);
- while (wpa_driver_wired_get_ifstatus(ifname, &status) == 0 &&
- status == 0)
- sleep(1);
- }
-#endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(FreeBSD_kernel__) */
return drv;
}
@@ -630,41 +389,8 @@ static void * wpa_driver_wired_init(void *ctx, const char *ifname)
static void wpa_driver_wired_deinit(void *priv)
{
struct wpa_driver_wired_data *drv = priv;
- int flags;
-
- if (drv->membership &&
- wired_multicast_membership(drv->pf_sock,
- if_nametoindex(drv->ifname),
- pae_group_addr, 0) < 0) {
- wpa_printf(MSG_DEBUG, "%s: Failed to remove PAE multicast "
- "group (PACKET)", __func__);
- }
-
- if (drv->multi &&
- wpa_driver_wired_multi(drv->ifname, pae_group_addr, 0) < 0) {
- wpa_printf(MSG_DEBUG, "%s: Failed to remove PAE multicast "
- "group (SIOCDELMULTI)", __func__);
- }
-
- if (drv->iff_allmulti &&
- (wpa_driver_wired_get_ifflags(drv->ifname, &flags) < 0 ||
- wpa_driver_wired_set_ifflags(drv->ifname,
- flags & ~IFF_ALLMULTI) < 0)) {
- wpa_printf(MSG_DEBUG, "%s: Failed to disable allmulti mode",
- __func__);
- }
-
- if (drv->iff_up &&
- wpa_driver_wired_get_ifflags(drv->ifname, &flags) == 0 &&
- (flags & IFF_UP) &&
- wpa_driver_wired_set_ifflags(drv->ifname, flags & ~IFF_UP) < 0) {
- wpa_printf(MSG_DEBUG, "%s: Failed to set the interface down",
- __func__);
- }
-
- if (drv->pf_sock != -1)
- close(drv->pf_sock);
+ driver_wired_deinit_common(&drv->common);
os_free(drv);
}
@@ -675,9 +401,9 @@ const struct wpa_driver_ops wpa_driver_wired_ops = {
.hapd_init = wired_driver_hapd_init,
.hapd_deinit = wired_driver_hapd_deinit,
.hapd_send_eapol = wired_send_eapol,
- .get_ssid = wpa_driver_wired_get_ssid,
- .get_bssid = wpa_driver_wired_get_bssid,
- .get_capa = wpa_driver_wired_get_capa,
+ .get_ssid = driver_wired_get_ssid,
+ .get_bssid = driver_wired_get_bssid,
+ .get_capa = driver_wired_get_capa,
.init = wpa_driver_wired_init,
.deinit = wpa_driver_wired_deinit,
};
diff --git a/freebsd/contrib/wpa/src/drivers/driver_wired_common.c b/freebsd/contrib/wpa/src/drivers/driver_wired_common.c
new file mode 100644
index 00000000..e9aab5df
--- /dev/null
+++ b/freebsd/contrib/wpa/src/drivers/driver_wired_common.c
@@ -0,0 +1,324 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Common functions for Wired Ethernet driver interfaces
+ * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004, Gunter Burchardt <tira@isx.de>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "eloop.h"
+#include "driver.h"
+#include "driver_wired_common.h"
+
+#include <sys/ioctl.h>
+#include <net/if.h>
+#ifdef __linux__
+#include <netpacket/packet.h>
+#include <net/if_arp.h>
+#include <net/if.h>
+#endif /* __linux__ */
+#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) */
+#ifdef __sun__
+#include <sys/sockio.h>
+#endif /* __sun__ */
+
+
+static int driver_wired_get_ifflags(const char *ifname, int *flags)
+{
+ struct ifreq ifr;
+ int s;
+
+ s = socket(PF_INET, SOCK_DGRAM, 0);
+ if (s < 0) {
+ wpa_printf(MSG_ERROR, "socket: %s", strerror(errno));
+ return -1;
+ }
+
+ os_memset(&ifr, 0, sizeof(ifr));
+ os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
+ if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
+ wpa_printf(MSG_ERROR, "ioctl[SIOCGIFFLAGS]: %s",
+ strerror(errno));
+ close(s);
+ return -1;
+ }
+ close(s);
+ *flags = ifr.ifr_flags & 0xffff;
+ return 0;
+}
+
+
+static int driver_wired_set_ifflags(const char *ifname, int flags)
+{
+ struct ifreq ifr;
+ int s;
+
+ s = socket(PF_INET, SOCK_DGRAM, 0);
+ if (s < 0) {
+ wpa_printf(MSG_ERROR, "socket: %s", strerror(errno));
+ return -1;
+ }
+
+ os_memset(&ifr, 0, sizeof(ifr));
+ os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
+ ifr.ifr_flags = flags & 0xffff;
+ if (ioctl(s, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
+ wpa_printf(MSG_ERROR, "ioctl[SIOCSIFFLAGS]: %s",
+ strerror(errno));
+ close(s);
+ return -1;
+ }
+ close(s);
+ return 0;
+}
+
+
+static int driver_wired_multi(const char *ifname, const u8 *addr, int add)
+{
+ struct ifreq ifr;
+ int s;
+
+#ifdef __sun__
+ return -1;
+#endif /* __sun__ */
+
+ s = socket(PF_INET, SOCK_DGRAM, 0);
+ if (s < 0) {
+ wpa_printf(MSG_ERROR, "socket: %s", strerror(errno));
+ return -1;
+ }
+
+ os_memset(&ifr, 0, sizeof(ifr));
+ os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
+#ifdef __linux__
+ ifr.ifr_hwaddr.sa_family = AF_UNSPEC;
+ os_memcpy(ifr.ifr_hwaddr.sa_data, addr, ETH_ALEN);
+#endif /* __linux__ */
+#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
+ {
+ struct sockaddr_dl *dlp;
+
+ dlp = (struct sockaddr_dl *) &ifr.ifr_addr;
+ dlp->sdl_len = sizeof(struct sockaddr_dl);
+ dlp->sdl_family = AF_LINK;
+ dlp->sdl_index = 0;
+ dlp->sdl_nlen = 0;
+ dlp->sdl_alen = ETH_ALEN;
+ dlp->sdl_slen = 0;
+ os_memcpy(LLADDR(dlp), addr, ETH_ALEN);
+ }
+#endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(FreeBSD_kernel__) */
+#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
+ {
+ struct sockaddr *sap;
+
+ sap = (struct sockaddr *) &ifr.ifr_addr;
+ sap->sa_len = sizeof(struct sockaddr);
+ sap->sa_family = AF_UNSPEC;
+ os_memcpy(sap->sa_data, addr, ETH_ALEN);
+ }
+#endif /* defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__) */
+
+ if (ioctl(s, add ? SIOCADDMULTI : SIOCDELMULTI, (caddr_t) &ifr) < 0) {
+ wpa_printf(MSG_ERROR, "ioctl[SIOC{ADD/DEL}MULTI]: %s",
+ strerror(errno));
+ close(s);
+ return -1;
+ }
+ close(s);
+ return 0;
+}
+
+
+int wired_multicast_membership(int sock, int ifindex, const u8 *addr, int add)
+{
+#ifdef __linux__
+ struct packet_mreq mreq;
+
+ if (sock < 0)
+ return -1;
+
+ os_memset(&mreq, 0, sizeof(mreq));
+ mreq.mr_ifindex = ifindex;
+ mreq.mr_type = PACKET_MR_MULTICAST;
+ mreq.mr_alen = ETH_ALEN;
+ os_memcpy(mreq.mr_address, addr, ETH_ALEN);
+
+ if (setsockopt(sock, SOL_PACKET,
+ add ? PACKET_ADD_MEMBERSHIP : PACKET_DROP_MEMBERSHIP,
+ &mreq, sizeof(mreq)) < 0) {
+ wpa_printf(MSG_ERROR, "setsockopt: %s", strerror(errno));
+ return -1;
+ }
+ return 0;
+#else /* __linux__ */
+ return -1;
+#endif /* __linux__ */
+}
+
+
+int driver_wired_get_ssid(void *priv, u8 *ssid)
+{
+ ssid[0] = 0;
+ return 0;
+}
+
+
+int driver_wired_get_bssid(void *priv, u8 *bssid)
+{
+ /* Report PAE group address as the "BSSID" for wired connection. */
+ os_memcpy(bssid, pae_group_addr, ETH_ALEN);
+ return 0;
+}
+
+
+int driver_wired_get_capa(void *priv, struct wpa_driver_capa *capa)
+{
+ os_memset(capa, 0, sizeof(*capa));
+ capa->flags = WPA_DRIVER_FLAGS_WIRED;
+ return 0;
+}
+
+
+#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
+static int driver_wired_get_ifstatus(const char *ifname, int *status)
+{
+ struct ifmediareq ifmr;
+ int s;
+
+ s = socket(PF_INET, SOCK_DGRAM, 0);
+ if (s < 0) {
+ wpa_printf(MSG_ERROR, "socket: %s", strerror(errno));
+ return -1;
+ }
+
+ os_memset(&ifmr, 0, sizeof(ifmr));
+ os_strlcpy(ifmr.ifm_name, ifname, IFNAMSIZ);
+ if (ioctl(s, SIOCGIFMEDIA, (caddr_t) &ifmr) < 0) {
+ wpa_printf(MSG_ERROR, "ioctl[SIOCGIFMEDIA]: %s",
+ strerror(errno));
+ close(s);
+ return -1;
+ }
+ close(s);
+ *status = (ifmr.ifm_status & (IFM_ACTIVE | IFM_AVALID)) ==
+ (IFM_ACTIVE | IFM_AVALID);
+
+ return 0;
+}
+#endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(FreeBSD_kernel__) */
+
+
+int driver_wired_init_common(struct driver_wired_common_data *common,
+ const char *ifname, void *ctx)
+{
+ int flags;
+
+ os_strlcpy(common->ifname, ifname, sizeof(common->ifname));
+ common->ctx = ctx;
+
+#ifdef __linux__
+ common->pf_sock = socket(PF_PACKET, SOCK_DGRAM, 0);
+ if (common->pf_sock < 0)
+ wpa_printf(MSG_ERROR, "socket(PF_PACKET): %s", strerror(errno));
+#else /* __linux__ */
+ common->pf_sock = -1;
+#endif /* __linux__ */
+
+ if (driver_wired_get_ifflags(ifname, &flags) == 0 &&
+ !(flags & IFF_UP) &&
+ driver_wired_set_ifflags(ifname, flags | IFF_UP) == 0)
+ common->iff_up = 1;
+
+ if (wired_multicast_membership(common->pf_sock,
+ if_nametoindex(common->ifname),
+ pae_group_addr, 1) == 0) {
+ wpa_printf(MSG_DEBUG,
+ "%s: Added multicast membership with packet socket",
+ __func__);
+ common->membership = 1;
+ } else if (driver_wired_multi(ifname, pae_group_addr, 1) == 0) {
+ wpa_printf(MSG_DEBUG,
+ "%s: Added multicast membership with SIOCADDMULTI",
+ __func__);
+ common->multi = 1;
+ } else if (driver_wired_get_ifflags(ifname, &flags) < 0) {
+ wpa_printf(MSG_INFO, "%s: Could not get interface flags",
+ __func__);
+ return -1;
+ } else if (flags & IFF_ALLMULTI) {
+ wpa_printf(MSG_DEBUG,
+ "%s: Interface is already configured for multicast",
+ __func__);
+ } else if (driver_wired_set_ifflags(ifname,
+ flags | IFF_ALLMULTI) < 0) {
+ wpa_printf(MSG_INFO, "%s: Failed to enable allmulti", __func__);
+ return -1;
+ } else {
+ wpa_printf(MSG_DEBUG, "%s: Enabled allmulti mode", __func__);
+ common->iff_allmulti = 1;
+ }
+#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
+ {
+ int status;
+
+ wpa_printf(MSG_DEBUG, "%s: waiting for link to become active",
+ __func__);
+ while (driver_wired_get_ifstatus(ifname, &status) == 0 &&
+ status == 0)
+ sleep(1);
+ }
+#endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(FreeBSD_kernel__) */
+
+ return 0;
+}
+
+
+void driver_wired_deinit_common(struct driver_wired_common_data *common)
+{
+ int flags;
+
+ if (common->membership &&
+ wired_multicast_membership(common->pf_sock,
+ if_nametoindex(common->ifname),
+ pae_group_addr, 0) < 0) {
+ wpa_printf(MSG_DEBUG,
+ "%s: Failed to remove PAE multicast group (PACKET)",
+ __func__);
+ }
+
+ if (common->multi &&
+ driver_wired_multi(common->ifname, pae_group_addr, 0) < 0) {
+ wpa_printf(MSG_DEBUG,
+ "%s: Failed to remove PAE multicast group (SIOCDELMULTI)",
+ __func__);
+ }
+
+ if (common->iff_allmulti &&
+ (driver_wired_get_ifflags(common->ifname, &flags) < 0 ||
+ driver_wired_set_ifflags(common->ifname,
+ flags & ~IFF_ALLMULTI) < 0)) {
+ wpa_printf(MSG_DEBUG, "%s: Failed to disable allmulti mode",
+ __func__);
+ }
+
+ if (common->iff_up &&
+ driver_wired_get_ifflags(common->ifname, &flags) == 0 &&
+ (flags & IFF_UP) &&
+ driver_wired_set_ifflags(common->ifname, flags & ~IFF_UP) < 0) {
+ wpa_printf(MSG_DEBUG, "%s: Failed to set the interface down",
+ __func__);
+ }
+
+ if (common->pf_sock != -1)
+ close(common->pf_sock);
+}
diff --git a/freebsd/contrib/wpa/src/drivers/driver_wired_common.h b/freebsd/contrib/wpa/src/drivers/driver_wired_common.h
new file mode 100644
index 00000000..2bb0710b
--- /dev/null
+++ b/freebsd/contrib/wpa/src/drivers/driver_wired_common.h
@@ -0,0 +1,34 @@
+/*
+ * Common definitions for Wired Ethernet driver interfaces
+ * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004, Gunter Burchardt <tira@isx.de>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef DRIVER_WIRED_COMMON_H
+#define DRIVER_WIRED_COMMON_H
+
+struct driver_wired_common_data {
+ char ifname[IFNAMSIZ + 1];
+ void *ctx;
+
+ int sock; /* raw packet socket for driver access */
+ int pf_sock;
+ int membership, multi, iff_allmulti, iff_up;
+};
+
+static const u8 pae_group_addr[ETH_ALEN] =
+{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 };
+
+int wired_multicast_membership(int sock, int ifindex, const u8 *addr, int add);
+int driver_wired_get_ssid(void *priv, u8 *ssid);
+int driver_wired_get_bssid(void *priv, u8 *bssid);
+int driver_wired_get_capa(void *priv, struct wpa_driver_capa *capa);
+
+int driver_wired_init_common(struct driver_wired_common_data *common,
+ const char *ifname, void *ctx);
+void driver_wired_deinit_common(struct driver_wired_common_data *common);
+
+#endif /* DRIVER_WIRED_COMMON_H */
diff --git a/freebsd/contrib/wpa/src/drivers/drivers.c b/freebsd/contrib/wpa/src/drivers/drivers.c
index ac83600e..0b9f3998 100644
--- a/freebsd/contrib/wpa/src/drivers/drivers.c
+++ b/freebsd/contrib/wpa/src/drivers/drivers.c
@@ -36,6 +36,9 @@ const struct wpa_driver_ops *const wpa_drivers[] =
#ifdef CONFIG_DRIVER_WIRED
&wpa_driver_wired_ops,
#endif /* CONFIG_DRIVER_WIRED */
+#ifdef CONFIG_DRIVER_MACSEC_LINUX
+ &wpa_driver_macsec_linux_ops,
+#endif /* CONFIG_DRIVER_MACSEC_LINUX */
#ifdef CONFIG_DRIVER_MACSEC_QCA
&wpa_driver_macsec_qca_ops,
#endif /* CONFIG_DRIVER_MACSEC_QCA */
diff --git a/freebsd/contrib/wpa/src/eap_peer/eap.c b/freebsd/contrib/wpa/src/eap_peer/eap.c
index 6a183071..c682b063 100644
--- a/freebsd/contrib/wpa/src/eap_peer/eap.c
+++ b/freebsd/contrib/wpa/src/eap_peer/eap.c
@@ -97,6 +97,14 @@ static void eap_notify_status(struct eap_sm *sm, const char *status,
}
+static void eap_report_error(struct eap_sm *sm, int error_code)
+{
+ wpa_printf(MSG_DEBUG, "EAP: Error notification: %d", error_code);
+ if (sm->eapol_cb->notify_eap_error)
+ sm->eapol_cb->notify_eap_error(sm->eapol_ctx, error_code);
+}
+
+
static void eap_sm_free_key(struct eap_sm *sm)
{
if (sm->eapKeyData) {
@@ -123,15 +131,17 @@ static void eap_deinit_prev_method(struct eap_sm *sm, const char *txt)
/**
- * eap_allowed_method - Check whether EAP method is allowed
+ * eap_config_allowed_method - Check whether EAP method is allowed
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
+ * @config: EAP configuration
* @vendor: Vendor-Id for expanded types or 0 = IETF for legacy types
* @method: EAP type
* Returns: 1 = allowed EAP method, 0 = not allowed
*/
-int eap_allowed_method(struct eap_sm *sm, int vendor, u32 method)
+static int eap_config_allowed_method(struct eap_sm *sm,
+ struct eap_peer_config *config,
+ int vendor, u32 method)
{
- struct eap_peer_config *config = eap_get_config(sm);
int i;
struct eap_method_type *m;
@@ -148,6 +158,57 @@ int eap_allowed_method(struct eap_sm *sm, int vendor, u32 method)
}
+/**
+ * eap_allowed_method - Check whether EAP method is allowed
+ * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
+ * @vendor: Vendor-Id for expanded types or 0 = IETF for legacy types
+ * @method: EAP type
+ * Returns: 1 = allowed EAP method, 0 = not allowed
+ */
+int eap_allowed_method(struct eap_sm *sm, int vendor, u32 method)
+{
+ return eap_config_allowed_method(sm, eap_get_config(sm), vendor,
+ method);
+}
+
+
+#if defined(PCSC_FUNCS) || defined(CONFIG_EAP_PROXY)
+static int eap_sm_append_3gpp_realm(struct eap_sm *sm, char *imsi,
+ size_t max_len, size_t *imsi_len,
+ int mnc_len)
+{
+ char *pos, mnc[4];
+
+ if (*imsi_len + 36 > max_len) {
+ wpa_printf(MSG_WARNING, "No room for realm in IMSI buffer");
+ return -1;
+ }
+
+ if (mnc_len != 2 && mnc_len != 3)
+ mnc_len = 3;
+
+ if (mnc_len == 2) {
+ mnc[0] = '0';
+ mnc[1] = imsi[3];
+ mnc[2] = imsi[4];
+ } else if (mnc_len == 3) {
+ mnc[0] = imsi[3];
+ mnc[1] = imsi[4];
+ mnc[2] = imsi[5];
+ }
+ mnc[3] = '\0';
+
+ pos = imsi + *imsi_len;
+ pos += os_snprintf(pos, imsi + max_len - pos,
+ "@wlan.mnc%s.mcc%c%c%c.3gppnetwork.org",
+ mnc, imsi[0], imsi[1], imsi[2]);
+ *imsi_len = pos - imsi;
+
+ return 0;
+}
+#endif /* PCSC_FUNCS || CONFIG_EAP_PROXY */
+
+
/*
* This state initializes state machine variables when the machine is
* activated (portEnabled = TRUE). This is also used when re-starting
@@ -373,9 +434,8 @@ nak:
#ifdef CONFIG_ERP
-static char * eap_home_realm(struct eap_sm *sm)
+static char * eap_get_realm(struct eap_sm *sm, struct eap_peer_config *config)
{
- struct eap_peer_config *config = eap_get_config(sm);
char *realm;
size_t i, realm_len;
@@ -415,7 +475,51 @@ static char * eap_home_realm(struct eap_sm *sm)
}
}
- return os_strdup("");
+#ifdef CONFIG_EAP_PROXY
+ /* When identity is not provided in the config, build the realm from
+ * IMSI for eap_proxy based methods.
+ */
+ if (!config->identity && !config->anonymous_identity &&
+ sm->eapol_cb->get_imsi &&
+ (eap_config_allowed_method(sm, config, EAP_VENDOR_IETF,
+ EAP_TYPE_SIM) ||
+ eap_config_allowed_method(sm, config, EAP_VENDOR_IETF,
+ EAP_TYPE_AKA) ||
+ eap_config_allowed_method(sm, config, EAP_VENDOR_IETF,
+ EAP_TYPE_AKA_PRIME))) {
+ char imsi[100];
+ size_t imsi_len;
+ int mnc_len, pos;
+
+ wpa_printf(MSG_DEBUG, "EAP: Build realm from IMSI (eap_proxy)");
+ mnc_len = sm->eapol_cb->get_imsi(sm->eapol_ctx, config->sim_num,
+ imsi, &imsi_len);
+ if (mnc_len < 0)
+ return NULL;
+
+ pos = imsi_len + 1; /* points to the beginning of the realm */
+ if (eap_sm_append_3gpp_realm(sm, imsi, sizeof(imsi), &imsi_len,
+ mnc_len) < 0) {
+ wpa_printf(MSG_WARNING, "Could not append realm");
+ return NULL;
+ }
+
+ realm = os_strdup(&imsi[pos]);
+ if (!realm)
+ return NULL;
+
+ wpa_printf(MSG_DEBUG, "EAP: Generated realm '%s'", realm);
+ return realm;
+ }
+#endif /* CONFIG_EAP_PROXY */
+
+ return NULL;
+}
+
+
+static char * eap_home_realm(struct eap_sm *sm)
+{
+ return eap_get_realm(sm, eap_get_config(sm));
}
@@ -471,6 +575,89 @@ static void eap_erp_remove_keys_realm(struct eap_sm *sm, const char *realm)
}
}
+
+int eap_peer_update_erp_next_seq_num(struct eap_sm *sm, u16 next_seq_num)
+{
+ struct eap_erp_key *erp;
+ char *home_realm;
+
+ home_realm = eap_home_realm(sm);
+ if (!home_realm || os_strlen(home_realm) == 0) {
+ os_free(home_realm);
+ return -1;
+ }
+
+ erp = eap_erp_get_key(sm, home_realm);
+ if (!erp) {
+ wpa_printf(MSG_DEBUG,
+ "EAP: Failed to find ERP key for realm: %s",
+ home_realm);
+ os_free(home_realm);
+ return -1;
+ }
+
+ if ((u32) next_seq_num < erp->next_seq) {
+ /* Sequence number has wrapped around, clear this ERP
+ * info and do a full auth next time.
+ */
+ eap_peer_erp_free_key(erp);
+ } else {
+ erp->next_seq = (u32) next_seq_num;
+ }
+
+ os_free(home_realm);
+ return 0;
+}
+
+
+int eap_peer_get_erp_info(struct eap_sm *sm, struct eap_peer_config *config,
+ const u8 **username, size_t *username_len,
+ const u8 **realm, size_t *realm_len,
+ u16 *erp_next_seq_num, const u8 **rrk,
+ size_t *rrk_len)
+{
+ struct eap_erp_key *erp;
+ char *home_realm;
+ char *pos;
+
+ if (config)
+ home_realm = eap_get_realm(sm, config);
+ else
+ home_realm = eap_home_realm(sm);
+ if (!home_realm || os_strlen(home_realm) == 0) {
+ os_free(home_realm);
+ return -1;
+ }
+
+ erp = eap_erp_get_key(sm, home_realm);
+ os_free(home_realm);
+ if (!erp)
+ return -1;
+
+ if (erp->next_seq >= 65536)
+ return -1; /* SEQ has range of 0..65535 */
+
+ pos = os_strchr(erp->keyname_nai, '@');
+ if (!pos)
+ return -1; /* this cannot really happen */
+ *username_len = pos - erp->keyname_nai;
+ *username = (u8 *) erp->keyname_nai;
+
+ pos++;
+ *realm_len = os_strlen(pos);
+ *realm = (u8 *) pos;
+
+ *erp_next_seq_num = (u16) erp->next_seq;
+
+ *rrk_len = erp->rRK_len;
+ *rrk = erp->rRK;
+
+ if (*username_len == 0 || *realm_len == 0 || *rrk_len == 0)
+ return -1;
+
+ return 0;
+}
+
#endif /* CONFIG_ERP */
@@ -485,13 +672,20 @@ void eap_peer_erp_free_keys(struct eap_sm *sm)
}
-static void eap_peer_erp_init(struct eap_sm *sm)
+/* Note: If ext_session and/or ext_emsk are passed to this function, they are
+ * expected to point to allocated memory and those allocations will be freed
+ * unconditionally. */
+void eap_peer_erp_init(struct eap_sm *sm, u8 *ext_session_id,
+ size_t ext_session_id_len, u8 *ext_emsk,
+ size_t ext_emsk_len)
{
#ifdef CONFIG_ERP
u8 *emsk = NULL;
size_t emsk_len = 0;
+ u8 *session_id = NULL;
+ size_t session_id_len = 0;
u8 EMSKname[EAP_EMSK_NAME_LEN];
- u8 len[2];
+ u8 len[2], ctx[3];
char *realm;
size_t realm_len, nai_buf_len;
struct eap_erp_key *erp = NULL;
@@ -499,7 +693,7 @@ static void eap_peer_erp_init(struct eap_sm *sm)
realm = eap_home_realm(sm);
if (!realm)
- return;
+ goto fail;
realm_len = os_strlen(realm);
wpa_printf(MSG_DEBUG, "EAP: Realm for ERP keyName-NAI: %s", realm);
eap_erp_remove_keys_realm(sm, realm);
@@ -519,7 +713,13 @@ static void eap_peer_erp_init(struct eap_sm *sm)
if (erp == NULL)
goto fail;
- emsk = sm->m->get_emsk(sm, sm->eap_method_priv, &emsk_len);
+ if (ext_emsk) {
+ emsk = ext_emsk;
+ emsk_len = ext_emsk_len;
+ } else {
+ emsk = sm->m->get_emsk(sm, sm->eap_method_priv, &emsk_len);
+ }
+
if (!emsk || emsk_len == 0 || emsk_len > ERP_MAX_KEY_LEN) {
wpa_printf(MSG_DEBUG,
"EAP: No suitable EMSK available for ERP");
@@ -528,10 +728,23 @@ static void eap_peer_erp_init(struct eap_sm *sm)
wpa_hexdump_key(MSG_DEBUG, "EAP: EMSK", emsk, emsk_len);
- WPA_PUT_BE16(len, 8);
- if (hmac_sha256_kdf(sm->eapSessionId, sm->eapSessionIdLen, "EMSK",
- len, sizeof(len),
- EMSKname, EAP_EMSK_NAME_LEN) < 0) {
+ if (ext_session_id) {
+ session_id = ext_session_id;
+ session_id_len = ext_session_id_len;
+ } else {
+ session_id = sm->eapSessionId;
+ session_id_len = sm->eapSessionIdLen;
+ }
+
+ if (!session_id || session_id_len == 0) {
+ wpa_printf(MSG_DEBUG,
+ "EAP: No suitable session id available for ERP");
+ goto fail;
+ }
+
+ WPA_PUT_BE16(len, EAP_EMSK_NAME_LEN);
+ if (hmac_sha256_kdf(session_id, session_id_len, "EMSK", len,
+ sizeof(len), EMSKname, EAP_EMSK_NAME_LEN) < 0) {
wpa_printf(MSG_DEBUG, "EAP: Could not derive EMSKname");
goto fail;
}
@@ -552,9 +765,11 @@ static void eap_peer_erp_init(struct eap_sm *sm)
erp->rRK_len = emsk_len;
wpa_hexdump_key(MSG_DEBUG, "EAP: ERP rRK", erp->rRK, erp->rRK_len);
+ ctx[0] = EAP_ERP_CS_HMAC_SHA256_128;
+ WPA_PUT_BE16(&ctx[1], erp->rRK_len);
if (hmac_sha256_kdf(erp->rRK, erp->rRK_len,
- "EAP Re-authentication Integrity Key@ietf.org",
- len, sizeof(len), erp->rIK, erp->rRK_len) < 0) {
+ "Re-authentication Integrity Key@ietf.org",
+ ctx, sizeof(ctx), erp->rIK, erp->rRK_len) < 0) {
wpa_printf(MSG_DEBUG, "EAP: Could not derive rIK for ERP");
goto fail;
}
@@ -565,7 +780,11 @@ static void eap_peer_erp_init(struct eap_sm *sm)
dl_list_add(&sm->erp_keys, &erp->list);
erp = NULL;
fail:
- bin_clear_free(emsk, emsk_len);
+ if (ext_emsk)
+ bin_clear_free(ext_emsk, ext_emsk_len);
+ else
+ bin_clear_free(emsk, emsk_len);
+ bin_clear_free(ext_session_id, ext_session_id_len);
bin_clear_free(erp, sizeof(*erp));
os_free(realm);
#endif /* CONFIG_ERP */
@@ -573,8 +792,7 @@ fail:
#ifdef CONFIG_ERP
-static int eap_peer_erp_reauth_start(struct eap_sm *sm,
- const struct eap_hdr *hdr, size_t len)
+struct wpabuf * eap_peer_build_erp_reauth_start(struct eap_sm *sm, u8 eap_id)
{
char *realm;
struct eap_erp_key *erp;
@@ -583,16 +801,16 @@ static int eap_peer_erp_reauth_start(struct eap_sm *sm,
realm = eap_home_realm(sm);
if (!realm)
- return -1;
+ return NULL;
erp = eap_erp_get_key(sm, realm);
os_free(realm);
realm = NULL;
if (!erp)
- return -1;
+ return NULL;
if (erp->next_seq >= 65536)
- return -1; /* SEQ has range of 0..65535 */
+ return NULL; /* SEQ has range of 0..65535 */
/* TODO: check rRK lifetime expiration */
@@ -601,9 +819,9 @@ static int eap_peer_erp_reauth_start(struct eap_sm *sm,
msg = eap_msg_alloc(EAP_VENDOR_IETF, (EapType) EAP_ERP_TYPE_REAUTH,
1 + 2 + 2 + os_strlen(erp->keyname_nai) + 1 + 16,
- EAP_CODE_INITIATE, hdr->identifier);
+ EAP_CODE_INITIATE, eap_id);
if (msg == NULL)
- return -1;
+ return NULL;
wpabuf_put_u8(msg, 0x20); /* Flags: R=0 B=0 L=1 */
wpabuf_put_be16(msg, erp->next_seq);
@@ -617,13 +835,28 @@ static int eap_peer_erp_reauth_start(struct eap_sm *sm,
if (hmac_sha256(erp->rIK, erp->rIK_len,
wpabuf_head(msg), wpabuf_len(msg), hash) < 0) {
wpabuf_free(msg);
- return -1;
+ return NULL;
}
wpabuf_put_data(msg, hash, 16);
- wpa_printf(MSG_DEBUG, "EAP: Sending EAP-Initiate/Re-auth");
sm->erp_seq = erp->next_seq;
erp->next_seq++;
+
+ wpa_hexdump_buf(MSG_DEBUG, "ERP: EAP-Initiate/Re-auth", msg);
+
+ return msg;
+}
+
+
+static int eap_peer_erp_reauth_start(struct eap_sm *sm, u8 eap_id)
+{
+ struct wpabuf *msg;
+
+ msg = eap_peer_build_erp_reauth_start(sm, eap_id);
+ if (!msg)
+ return -1;
+
+ wpa_printf(MSG_DEBUG, "EAP: Sending EAP-Initiate/Re-auth");
wpabuf_free(sm->eapRespData);
sm->eapRespData = msg;
sm->reauthInit = TRUE;
@@ -693,8 +926,6 @@ SM_STATE(EAP, METHOD)
if (sm->m->isKeyAvailable && sm->m->getKey &&
sm->m->isKeyAvailable(sm, sm->eap_method_priv)) {
- struct eap_peer_config *config = eap_get_config(sm);
-
eap_sm_free_key(sm);
sm->eapKeyData = sm->m->getKey(sm, sm->eap_method_priv,
&sm->eapKeyDataLen);
@@ -707,8 +938,6 @@ SM_STATE(EAP, METHOD)
wpa_hexdump(MSG_DEBUG, "EAP: Session-Id",
sm->eapSessionId, sm->eapSessionIdLen);
}
- if (config->erp && sm->m->get_emsk && sm->eapSessionId)
- eap_peer_erp_init(sm);
}
}
@@ -806,6 +1035,8 @@ SM_STATE(EAP, RETRANSMIT)
*/
SM_STATE(EAP, SUCCESS)
{
+ struct eap_peer_config *config = eap_get_config(sm);
+
SM_ENTRY(EAP, SUCCESS);
if (sm->eapKeyData != NULL)
sm->eapKeyAvailable = TRUE;
@@ -828,6 +1059,11 @@ SM_STATE(EAP, SUCCESS)
wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
"EAP authentication completed successfully");
+
+ if (config->erp && sm->m->get_emsk && sm->eapSessionId &&
+ sm->m->isKeyAvailable &&
+ sm->m->isKeyAvailable(sm, sm->eap_method_priv))
+ eap_peer_erp_init(sm, NULL, 0, NULL, 0);
}
@@ -1278,48 +1514,6 @@ static int mnc_len_from_imsi(const char *imsi)
}
-static int eap_sm_append_3gpp_realm(struct eap_sm *sm, char *imsi,
- size_t max_len, size_t *imsi_len)
-{
- int mnc_len;
- char *pos, mnc[4];
-
- if (*imsi_len + 36 > max_len) {
- wpa_printf(MSG_WARNING, "No room for realm in IMSI buffer");
- return -1;
- }
-
- /* MNC (2 or 3 digits) */
- mnc_len = scard_get_mnc_len(sm->scard_ctx);
- if (mnc_len < 0)
- mnc_len = mnc_len_from_imsi(imsi);
- if (mnc_len < 0) {
- wpa_printf(MSG_INFO, "Failed to get MNC length from (U)SIM "
- "assuming 3");
- mnc_len = 3;
- }
-
- if (mnc_len == 2) {
- mnc[0] = '0';
- mnc[1] = imsi[3];
- mnc[2] = imsi[4];
- } else if (mnc_len == 3) {
- mnc[0] = imsi[3];
- mnc[1] = imsi[4];
- mnc[2] = imsi[5];
- }
- mnc[3] = '\0';
-
- pos = imsi + *imsi_len;
- pos += os_snprintf(pos, imsi + max_len - pos,
- "@wlan.mnc%s.mcc%c%c%c.3gppnetwork.org",
- mnc, imsi[0], imsi[1], imsi[2]);
- *imsi_len = pos - imsi;
-
- return 0;
-}
-
-
static int eap_sm_imsi_identity(struct eap_sm *sm,
struct eap_peer_config *conf)
{
@@ -1327,7 +1521,7 @@ static int eap_sm_imsi_identity(struct eap_sm *sm,
char imsi[100];
size_t imsi_len;
struct eap_method_type *m = conf->eap_methods;
- int i;
+ int i, mnc_len;
imsi_len = sizeof(imsi);
if (scard_get_imsi(sm->scard_ctx, imsi, &imsi_len)) {
@@ -1342,7 +1536,18 @@ static int eap_sm_imsi_identity(struct eap_sm *sm,
return -1;
}
- if (eap_sm_append_3gpp_realm(sm, imsi, sizeof(imsi), &imsi_len) < 0) {
+ /* MNC (2 or 3 digits) */
+ mnc_len = scard_get_mnc_len(sm->scard_ctx);
+ if (mnc_len < 0)
+ mnc_len = mnc_len_from_imsi(imsi);
+ if (mnc_len < 0) {
+ wpa_printf(MSG_INFO, "Failed to get MNC length from (U)SIM "
+ "assuming 3");
+ mnc_len = 3;
+ }
+
+ if (eap_sm_append_3gpp_realm(sm, imsi, sizeof(imsi), &imsi_len,
+ mnc_len) < 0) {
wpa_printf(MSG_WARNING, "Could not add realm to SIM identity");
return -1;
}
@@ -1568,7 +1773,7 @@ static void eap_peer_initiate(struct eap_sm *sm, const struct eap_hdr *hdr,
/* TODO: Derivation of domain specific keys for local ER */
}
- if (eap_peer_erp_reauth_start(sm, hdr, len) == 0)
+ if (eap_peer_erp_reauth_start(sm, hdr->identifier) == 0)
return;
invalid:
@@ -1579,8 +1784,7 @@ invalid:
}
-static void eap_peer_finish(struct eap_sm *sm, const struct eap_hdr *hdr,
- size_t len)
+void eap_peer_finish(struct eap_sm *sm, const struct eap_hdr *hdr, size_t len)
{
#ifdef CONFIG_ERP
const u8 *pos = (const u8 *) (hdr + 1);
@@ -1830,6 +2034,15 @@ static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req)
case EAP_CODE_FAILURE:
wpa_printf(MSG_DEBUG, "EAP: Received EAP-Failure");
eap_notify_status(sm, "completion", "failure");
+
+ /* Get the error code from method */
+ if (sm->m && sm->m->get_error_code) {
+ int error_code;
+
+ error_code = sm->m->get_error_code(sm->eap_method_priv);
+ if (error_code != NO_EAP_METHOD_ERROR)
+ eap_report_error(sm, error_code);
+ }
sm->rxFailure = TRUE;
break;
case EAP_CODE_INITIATE:
@@ -2233,6 +2446,7 @@ static void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field,
config->pending_req_passphrase++;
break;
case WPA_CTRL_REQ_SIM:
+ config->pending_req_sim++;
txt = msg;
break;
case WPA_CTRL_REQ_EXT_CERT_CHECK:
diff --git a/freebsd/contrib/wpa/src/eap_peer/eap.h b/freebsd/contrib/wpa/src/eap_peer/eap.h
index 1a645af8..d0837e37 100644
--- a/freebsd/contrib/wpa/src/eap_peer/eap.h
+++ b/freebsd/contrib/wpa/src/eap_peer/eap.h
@@ -246,12 +246,37 @@ struct eapol_callbacks {
void (*notify_status)(void *ctx, const char *status,
const char *parameter);
+ /**
+ * notify_eap_error - Report EAP method error code
+ * @ctx: eapol_ctx from eap_peer_sm_init() call
+ * @error_code: Error code from the used EAP method
+ */
+ void (*notify_eap_error)(void *ctx, int error_code);
+
#ifdef CONFIG_EAP_PROXY
/**
* eap_proxy_cb - Callback signifying any updates from eap_proxy
* @ctx: eapol_ctx from eap_peer_sm_init() call
*/
void (*eap_proxy_cb)(void *ctx);
+
+ /**
+ * eap_proxy_notify_sim_status - Notification of SIM status change
+ * @ctx: eapol_ctx from eap_peer_sm_init() call
+ * @sim_state: One of enum value from sim_state
+ */
+ void (*eap_proxy_notify_sim_status)(void *ctx,
+ enum eap_proxy_sim_state sim_state);
+
+ /**
+ * get_imsi - Get the IMSI value from eap_proxy
+ * @ctx: eapol_ctx from eap_peer_sm_init() call
+ * @sim_num: SIM/USIM number to get the IMSI value for
+ * @imsi: Buffer for IMSI value
+ * @len: Buffer for returning IMSI length in octets
+ * Returns: MNC length (2 or 3) or -1 on error
+ */
+ int (*get_imsi)(void *ctx, int sim_num, char *imsi, size_t *len);
#endif /* CONFIG_EAP_PROXY */
/**
@@ -348,6 +373,16 @@ void eap_sm_set_ext_pw_ctx(struct eap_sm *sm, struct ext_password_data *ext);
void eap_set_anon_id(struct eap_sm *sm, const u8 *id, size_t len);
int eap_peer_was_failure_expected(struct eap_sm *sm);
void eap_peer_erp_free_keys(struct eap_sm *sm);
+struct wpabuf * eap_peer_build_erp_reauth_start(struct eap_sm *sm, u8 eap_id);
+void eap_peer_finish(struct eap_sm *sm, const struct eap_hdr *hdr, size_t len);
+int eap_peer_get_erp_info(struct eap_sm *sm, struct eap_peer_config *config,
+ const u8 **username, size_t *username_len,
+ const u8 **realm, size_t *realm_len, u16 *erp_seq_num,
+ const u8 **rrk, size_t *rrk_len);
+int eap_peer_update_erp_next_seq_num(struct eap_sm *sm, u16 seq_num);
+void eap_peer_erp_init(struct eap_sm *sm, u8 *ext_session_id,
+ size_t ext_session_id_len, u8 *ext_emsk,
+ size_t ext_emsk_len);
#endif /* IEEE8021X_EAPOL */
diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_config.h b/freebsd/contrib/wpa/src/eap_peer/eap_config.h
index f9800726..3a88f2ab 100644
--- a/freebsd/contrib/wpa/src/eap_peer/eap_config.h
+++ b/freebsd/contrib/wpa/src/eap_peer/eap_config.h
@@ -46,6 +46,9 @@ struct eap_peer_config {
*/
size_t anonymous_identity_len;
+ u8 *imsi_identity;
+ size_t imsi_identity_len;
+
/**
* password - Password string for EAP
*
@@ -98,7 +101,7 @@ struct eap_peer_config {
* certificate store (My user account) is used, whereas computer store
* (Computer account) is used when running wpasvc as a service.
*/
- u8 *ca_cert;
+ char *ca_cert;
/**
* ca_path - Directory path for CA certificate files (PEM)
@@ -109,7 +112,7 @@ struct eap_peer_config {
* these certificates are added to the list of trusted CAs. ca_cert
* may also be included in that case, but it is not required.
*/
- u8 *ca_path;
+ char *ca_path;
/**
* client_cert - File path to client certificate file (PEM/DER)
@@ -123,7 +126,7 @@ struct eap_peer_config {
* Alternatively, a named configuration blob can be used by setting
* this to blob://blob_name.
*/
- u8 *client_cert;
+ char *client_cert;
/**
* private_key - File path to client private key file (PEM/DER/PFX)
@@ -150,7 +153,7 @@ struct eap_peer_config {
* Alternatively, a named configuration blob can be used by setting
* this to blob://blob_name.
*/
- u8 *private_key;
+ char *private_key;
/**
* private_key_passwd - Password for private key file
@@ -175,7 +178,7 @@ struct eap_peer_config {
* Alternatively, a named configuration blob can be used by setting
* this to blob://blob_name.
*/
- u8 *dh_file;
+ char *dh_file;
/**
* subject_match - Constraint for server certificate subject
@@ -191,7 +194,49 @@ struct eap_peer_config {
* to do a suffix match against a possible domain name in the CN entry.
* For such a use case, domain_suffix_match should be used instead.
*/
- u8 *subject_match;
+ char *subject_match;
+
+ /**
+ * check_cert_subject - Constraint for server certificate subject fields
+ *
+ * If check_cert_subject is set, the value of every field will be
+ * checked against the DN of the subject in the authentication server
+ * certificate. If the values do not match, the certificate verification
+ * will fail, rejecting the server. This option allows wpa_supplicant to
+ * match every individual field in the right order against the DN of the
+ * subject in the server certificate.
+ *
+ * For example, check_cert_subject=C=US/O=XX/OU=ABC/OU=XYZ/CN=1234 will
+ * check every individual DN field of the subject in the server
+ * certificate. If OU=XYZ comes first in terms of the order in the
+ * server certificate (DN field of server certificate
+ * C=US/O=XX/OU=XYZ/OU=ABC/CN=1234), wpa_supplicant will reject the
+ * server because the order of 'OU' is not matching the specified string
+ * in check_cert_subject.
+ *
+ * This option also allows '*' as a wildcard. This option has some
+ * limitation.
+ * It can only be used as per the following example.
+ *
+ * For example, check_cert_subject=C=US/O=XX/OU=Production* and we have
+ * two servers and DN of the subject in the first server certificate is
+ * (C=US/O=XX/OU=Production Unit) and DN of the subject in the second
+ * server is (C=US/O=XX/OU=Production Factory). In this case,
+ * wpa_supplicant will allow both servers because the value of 'OU'
+ * field in both server certificates matches 'OU' value in
+ * 'check_cert_subject' up to 'wildcard'.
+ *
+ * (Allow all servers, e.g., check_cert_subject=*)
+ */
+ char *check_cert_subject;
+
+ /**
+ * check_cert_subject2 - Constraint for server certificate subject fields
+ *
+ * This field is like check_cert_subject, but used for phase 2 (inside
+ * EAP-TTLS/PEAP/FAST tunnel) authentication.
+ */
+ char *check_cert_subject2;
/**
* altsubject_match - Constraint for server certificate alt. subject
@@ -209,23 +254,26 @@ struct eap_peer_config {
*
* Following types are supported: EMAIL, DNS, URI
*/
- u8 *altsubject_match;
+ char *altsubject_match;
/**
* domain_suffix_match - Constraint for server domain name
*
- * If set, this FQDN is used as a suffix match requirement for the
- * server certificate in SubjectAltName dNSName element(s). If a
- * matching dNSName is found, this constraint is met. If no dNSName
- * values are present, this constraint is matched against SubjectName CN
- * using same suffix match comparison. Suffix match here means that the
- * host/domain name is compared one label at a time starting from the
- * top-level domain and all the labels in domain_suffix_match shall be
- * included in the certificate. The certificate may include additional
- * sub-level labels in addition to the required labels.
+ * If set, this semicolon deliminated list of FQDNs is used as suffix
+ * match requirements for the server certificate in SubjectAltName
+ * dNSName element(s). If a matching dNSName is found against any of the
+ * specified values, this constraint is met. If no dNSName values are
+ * present, this constraint is matched against SubjectName CN using same
+ * suffix match comparison. Suffix match here means that the host/domain
+ * name is compared case-insentively one label at a time starting from
+ * the top-level domain and all the labels in domain_suffix_match shall
+ * be included in the certificate. The certificate may include
+ * additional sub-level labels in addition to the required labels.
*
* For example, domain_suffix_match=example.com would match
- * test.example.com but would not match test-example.com.
+ * test.example.com but would not match test-example.com. Multiple
+ * match options can be specified in following manner:
+ * example.org;example.com.
*/
char *domain_suffix_match;
@@ -241,6 +289,12 @@ struct eap_peer_config {
* no subdomains or wildcard matches are allowed. Case-insensitive
* comparison is used, so "Example.com" matches "example.com", but would
* not match "test.Example.com".
+ *
+ * More than one match string can be provided by using semicolons to
+ * separate the strings (e.g., example.org;example.com). When multiple
+ * strings are specified, a match with any one of the values is
+ * considered a sufficient match for the certificate, i.e., the
+ * conditions are ORed together.
*/
char *domain_match;
@@ -260,7 +314,7 @@ struct eap_peer_config {
* Alternatively, a named configuration blob can be used by setting
* this to blob://blob_name.
*/
- u8 *ca_cert2;
+ char *ca_cert2;
/**
* ca_path2 - Directory path for CA certificate files (PEM) (Phase 2)
@@ -274,7 +328,7 @@ struct eap_peer_config {
* This field is like ca_path, but used for phase 2 (inside
* EAP-TTLS/PEAP/FAST tunnel) authentication.
*/
- u8 *ca_path2;
+ char *ca_path2;
/**
* client_cert2 - File path to client certificate file
@@ -287,7 +341,7 @@ struct eap_peer_config {
* Alternatively, a named configuration blob can be used by setting
* this to blob://blob_name.
*/
- u8 *client_cert2;
+ char *client_cert2;
/**
* private_key2 - File path to client private key file
@@ -300,7 +354,7 @@ struct eap_peer_config {
* Alternatively, a named configuration blob can be used by setting
* this to blob://blob_name.
*/
- u8 *private_key2;
+ char *private_key2;
/**
* private_key2_passwd - Password for private key file
@@ -321,7 +375,7 @@ struct eap_peer_config {
* Alternatively, a named configuration blob can be used by setting
* this to blob://blob_name.
*/
- u8 *dh_file2;
+ char *dh_file2;
/**
* subject_match2 - Constraint for server certificate subject
@@ -329,7 +383,7 @@ struct eap_peer_config {
* This field is like subject_match, but used for phase 2 (inside
* EAP-TTLS/PEAP/FAST tunnel) authentication.
*/
- u8 *subject_match2;
+ char *subject_match2;
/**
* altsubject_match2 - Constraint for server certificate alt. subject
@@ -337,7 +391,7 @@ struct eap_peer_config {
* This field is like altsubject_match, but used for phase 2 (inside
* EAP-TTLS/PEAP/FAST tunnel) authentication.
*/
- u8 *altsubject_match2;
+ char *altsubject_match2;
/**
* domain_suffix_match2 - Constraint for server domain name
@@ -628,6 +682,15 @@ struct eap_peer_config {
int pending_req_passphrase;
/**
+ * pending_req_sim - Pending SIM request
+ *
+ * This field should not be set in configuration step. It is only used
+ * internally when control interface is used to request needed
+ * information.
+ */
+ int pending_req_sim;
+
+ /**
* pending_req_otp - Whether there is a pending OTP request
*
* This field should not be set in configuration step. It is only used
diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_i.h b/freebsd/contrib/wpa/src/eap_peer/eap_i.h
index 6ab24834..096f0f28 100644
--- a/freebsd/contrib/wpa/src/eap_peer/eap_i.h
+++ b/freebsd/contrib/wpa/src/eap_peer/eap_i.h
@@ -14,6 +14,8 @@
#include "eap_peer/eap.h"
#include "eap_common/eap_common.h"
+#define NO_EAP_METHOD_ERROR (-1)
+
/* RFC 4137 - EAP Peer state machine */
typedef enum {
@@ -206,6 +208,17 @@ struct eap_method {
const u8 * (*get_identity)(struct eap_sm *sm, void *priv, size_t *len);
/**
+ * get_error_code - Get the latest EAP method error code
+ * @priv: Pointer to private EAP method data from eap_method::init()
+ * Returns: An int for the EAP method specific error code if exists or
+ * NO_EAP_METHOD_ERROR otherwise.
+ *
+ * This method is an optional handler that only EAP methods that need to
+ * report their error code need to implement.
+ */
+ int (*get_error_code)(void *priv);
+
+ /**
* free - Free EAP method data
* @method: Pointer to the method data registered with
* eap_peer_method_register().
diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_leap.c b/freebsd/contrib/wpa/src/eap_peer/eap_leap.c
index af63bf88..5f087bf5 100644
--- a/freebsd/contrib/wpa/src/eap_peer/eap_leap.c
+++ b/freebsd/contrib/wpa/src/eap_peer/eap_leap.c
@@ -117,10 +117,14 @@ static struct wpabuf * eap_leap_process_request(struct eap_sm *sm, void *priv,
wpabuf_put_u8(resp, 0); /* unused */
wpabuf_put_u8(resp, LEAP_RESPONSE_LEN);
rpos = wpabuf_put(resp, LEAP_RESPONSE_LEN);
- if (pwhash)
- challenge_response(challenge, password, rpos);
- else
- nt_challenge_response(challenge, password, password_len, rpos);
+ if ((pwhash && challenge_response(challenge, password, rpos)) ||
+ (!pwhash &&
+ nt_challenge_response(challenge, password, password_len, rpos))) {
+ wpa_printf(MSG_DEBUG, "EAP-LEAP: Failed to derive response");
+ ret->ignore = TRUE;
+ wpabuf_free(resp);
+ return NULL;
+ }
os_memcpy(data->peer_response, rpos, LEAP_RESPONSE_LEN);
wpa_hexdump(MSG_MSGDUMP, "EAP-LEAP: Response",
rpos, LEAP_RESPONSE_LEN);
@@ -241,7 +245,10 @@ static struct wpabuf * eap_leap_process_response(struct eap_sm *sm, void *priv,
return NULL;
}
}
- challenge_response(data->ap_challenge, pw_hash_hash, expected);
+ if (challenge_response(data->ap_challenge, pw_hash_hash, expected)) {
+ ret->ignore = TRUE;
+ return NULL;
+ }
ret->methodState = METHOD_DONE;
ret->allowNotifications = FALSE;
diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_mschapv2.c b/freebsd/contrib/wpa/src/eap_peer/eap_mschapv2.c
index 9193a772..25ead777 100644
--- a/freebsd/contrib/wpa/src/eap_peer/eap_mschapv2.c
+++ b/freebsd/contrib/wpa/src/eap_peer/eap_mschapv2.c
@@ -111,23 +111,21 @@ static void * eap_mschapv2_init(struct eap_sm *sm)
return NULL;
if (sm->peer_challenge) {
- data->peer_challenge = os_malloc(MSCHAPV2_CHAL_LEN);
+ data->peer_challenge = os_memdup(sm->peer_challenge,
+ MSCHAPV2_CHAL_LEN);
if (data->peer_challenge == NULL) {
eap_mschapv2_deinit(sm, data);
return NULL;
}
- os_memcpy(data->peer_challenge, sm->peer_challenge,
- MSCHAPV2_CHAL_LEN);
}
if (sm->auth_challenge) {
- data->auth_challenge = os_malloc(MSCHAPV2_CHAL_LEN);
+ data->auth_challenge = os_memdup(sm->auth_challenge,
+ MSCHAPV2_CHAL_LEN);
if (data->auth_challenge == NULL) {
eap_mschapv2_deinit(sm, data);
return NULL;
}
- os_memcpy(data->auth_challenge, sm->auth_challenge,
- MSCHAPV2_CHAL_LEN);
}
data->phase2 = sm->init_phase2;
@@ -569,11 +567,11 @@ static struct wpabuf * eap_mschapv2_change_password(
if (pwhash) {
u8 new_password_hash[16];
if (nt_password_hash(new_password, new_password_len,
- new_password_hash))
+ new_password_hash) ||
+ nt_password_hash_encrypted_with_block(password,
+ new_password_hash,
+ cp->encr_hash))
goto fail;
- nt_password_hash_encrypted_with_block(password,
- new_password_hash,
- cp->encr_hash);
} else {
if (old_nt_password_hash_encrypted_with_new_nt_password_hash(
new_password, new_password_len,
@@ -860,9 +858,13 @@ static u8 * eap_mschapv2_getKey(struct eap_sm *sm, void *priv, size_t *len)
/* MSK = server MS-MPPE-Recv-Key | MS-MPPE-Send-Key, i.e.,
* peer MS-MPPE-Send-Key | MS-MPPE-Recv-Key */
- get_asymetric_start_key(data->master_key, key, MSCHAPV2_KEY_LEN, 1, 0);
- get_asymetric_start_key(data->master_key, key + MSCHAPV2_KEY_LEN,
- MSCHAPV2_KEY_LEN, 0, 0);
+ if (get_asymetric_start_key(data->master_key, key, MSCHAPV2_KEY_LEN, 1,
+ 0) < 0 ||
+ get_asymetric_start_key(data->master_key, key + MSCHAPV2_KEY_LEN,
+ MSCHAPV2_KEY_LEN, 0, 0) < 0) {
+ os_free(key);
+ return NULL;
+ }
wpa_hexdump_key(MSG_DEBUG, "EAP-MSCHAPV2: Derived key",
key, key_len);
diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_peap.c b/freebsd/contrib/wpa/src/eap_peer/eap_peap.c
index ab270bbc..74bc2653 100644
--- a/freebsd/contrib/wpa/src/eap_peer/eap_peap.c
+++ b/freebsd/contrib/wpa/src/eap_peer/eap_peap.c
@@ -2,7 +2,7 @@
/*
* EAP peer method: EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-10.txt)
- * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -171,7 +171,7 @@ static void * eap_peap_init(struct eap_sm *sm)
static void eap_peap_free_key(struct eap_peap_data *data)
{
if (data->key_data) {
- bin_clear_free(data->key_data, EAP_TLS_KEY_LEN);
+ bin_clear_free(data->key_data, EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
data->key_data = NULL;
}
}
@@ -188,9 +188,9 @@ static void eap_peap_deinit(struct eap_sm *sm, void *priv)
eap_peer_tls_ssl_deinit(sm, &data->ssl);
eap_peap_free_key(data);
os_free(data->session_id);
- wpabuf_free(data->pending_phase2_req);
- wpabuf_free(data->pending_resp);
- os_free(data);
+ wpabuf_clear_free(data->pending_phase2_req);
+ wpabuf_clear_free(data->pending_resp);
+ bin_clear_free(data, sizeof(*data));
}
@@ -255,7 +255,7 @@ static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data)
{
u8 *tk;
u8 isk[32], imck[60];
- int resumed;
+ int resumed, res;
/*
* Tunnel key (TK) is the first 60 octets of the key generated by
@@ -294,9 +294,11 @@ static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data)
* in the end of the label just before ISK; is that just a typo?)
*/
wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TempKey", tk, 40);
- if (peap_prfplus(data->peap_version, tk, 40,
- "Inner Methods Compound Keys",
- isk, sizeof(isk), imck, sizeof(imck)) < 0)
+ res = peap_prfplus(data->peap_version, tk, 40,
+ "Inner Methods Compound Keys",
+ isk, sizeof(isk), imck, sizeof(imck));
+ os_memset(isk, 0, sizeof(isk));
+ if (res < 0)
return -1;
wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IMCK (IPMKj)",
imck, sizeof(imck));
@@ -305,6 +307,7 @@ static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data)
wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK (S-IPMKj)", data->ipmk, 40);
os_memcpy(data->cmk, imck + 40, 20);
wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK (CMKj)", data->cmk, 20);
+ os_memset(imck, 0, sizeof(imck));
return 0;
}
@@ -384,7 +387,7 @@ static struct wpabuf * eap_tlv_build_result(struct eap_sm *sm,
wpabuf_put_be16(msg, status); /* Status */
if (crypto_tlv_used && eap_tlv_add_cryptobinding(sm, data, msg)) {
- wpabuf_free(msg);
+ wpabuf_clear_free(msg);
return NULL;
}
@@ -653,11 +656,11 @@ static int eap_peap_phase2_request(struct eap_sm *sm,
if (*resp == NULL) {
ret->methodState = METHOD_DONE;
ret->decision = DECISION_FAIL;
- wpabuf_free(buf);
+ wpabuf_clear_free(buf);
return -1;
}
wpabuf_put_buf(*resp, buf);
- wpabuf_free(buf);
+ wpabuf_clear_free(buf);
break;
}
}
@@ -728,8 +731,9 @@ static int eap_peap_phase2_request(struct eap_sm *sm,
if (*resp == NULL &&
(config->pending_req_identity || config->pending_req_password ||
- config->pending_req_otp || config->pending_req_new_password)) {
- wpabuf_free(data->pending_phase2_req);
+ config->pending_req_otp || config->pending_req_new_password ||
+ config->pending_req_sim)) {
+ wpabuf_clear_free(data->pending_phase2_req);
data->pending_phase2_req = wpabuf_alloc_copy(hdr, len);
}
@@ -808,7 +812,7 @@ continue_req:
struct wpabuf *nmsg = wpabuf_alloc(sizeof(struct eap_hdr) +
wpabuf_len(in_decrypted));
if (nmsg == NULL) {
- wpabuf_free(in_decrypted);
+ wpabuf_clear_free(in_decrypted);
return 0;
}
nhdr = wpabuf_put(nmsg, sizeof(*nhdr));
@@ -818,7 +822,7 @@ continue_req:
nhdr->length = host_to_be16(sizeof(struct eap_hdr) +
wpabuf_len(in_decrypted));
- wpabuf_free(in_decrypted);
+ wpabuf_clear_free(in_decrypted);
in_decrypted = nmsg;
}
@@ -827,7 +831,7 @@ continue_req:
wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 "
"EAP frame (len=%lu)",
(unsigned long) wpabuf_len(in_decrypted));
- wpabuf_free(in_decrypted);
+ wpabuf_clear_free(in_decrypted);
return 0;
}
len = be_to_host16(hdr->length);
@@ -836,7 +840,7 @@ continue_req:
"Phase 2 EAP frame (len=%lu hdr->length=%lu)",
(unsigned long) wpabuf_len(in_decrypted),
(unsigned long) len);
- wpabuf_free(in_decrypted);
+ wpabuf_clear_free(in_decrypted);
return 0;
}
if (len < wpabuf_len(in_decrypted)) {
@@ -853,7 +857,7 @@ continue_req:
case EAP_CODE_REQUEST:
if (eap_peap_phase2_request(sm, data, ret, in_decrypted,
&resp)) {
- wpabuf_free(in_decrypted);
+ wpabuf_clear_free(in_decrypted);
wpa_printf(MSG_INFO, "EAP-PEAP: Phase2 Request "
"processing failed");
return 0;
@@ -873,7 +877,7 @@ continue_req:
"completed successfully");
ret->methodState = METHOD_DONE;
ret->decision = DECISION_FAIL;
- wpabuf_free(in_decrypted);
+ wpabuf_clear_free(in_decrypted);
return 0;
}
wpa_printf(MSG_DEBUG, "EAP-PEAP: Version 1 - "
@@ -883,7 +887,7 @@ continue_req:
ret->methodState = METHOD_DONE;
data->phase2_success = 1;
if (data->peap_outer_success == 2) {
- wpabuf_free(in_decrypted);
+ wpabuf_clear_free(in_decrypted);
wpa_printf(MSG_DEBUG, "EAP-PEAP: Use TLS ACK "
"to finish authentication");
return 1;
@@ -929,7 +933,7 @@ continue_req:
break;
}
- wpabuf_free(in_decrypted);
+ wpabuf_clear_free(in_decrypted);
if (resp) {
int skip_change2 = 0;
@@ -956,7 +960,7 @@ continue_req:
wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt "
"a Phase 2 frame");
}
- wpabuf_free(resp);
+ wpabuf_clear_free(resp);
}
return 0;
@@ -1057,7 +1061,7 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv,
if (sm->waiting_ext_cert_check) {
wpa_printf(MSG_DEBUG,
"EAP-PEAP: Waiting external server certificate validation");
- wpabuf_free(data->pending_resp);
+ wpabuf_clear_free(data->pending_resp);
data->pending_resp = resp;
return NULL;
}
@@ -1082,12 +1086,19 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv,
"key derivation", label);
data->key_data =
eap_peer_tls_derive_key(sm, &data->ssl, label,
- EAP_TLS_KEY_LEN);
+ NULL, 0,
+ EAP_TLS_KEY_LEN +
+ EAP_EMSK_LEN);
if (data->key_data) {
- wpa_hexdump_key(MSG_DEBUG,
+ wpa_hexdump_key(MSG_DEBUG,
"EAP-PEAP: Derived key",
data->key_data,
EAP_TLS_KEY_LEN);
+ wpa_hexdump_key(MSG_DEBUG,
+ "EAP-PEAP: Derived EMSK",
+ data->key_data +
+ EAP_TLS_KEY_LEN,
+ EAP_EMSK_LEN);
} else {
wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to "
"derive key");
@@ -1132,7 +1143,7 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv,
/*
* Application data included in the handshake message.
*/
- wpabuf_free(data->pending_phase2_req);
+ wpabuf_clear_free(data->pending_phase2_req);
data->pending_phase2_req = resp;
resp = NULL;
res = eap_peap_decrypt(sm, data, ret, req, &msg,
@@ -1145,7 +1156,7 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv,
}
if (res == 1) {
- wpabuf_free(resp);
+ wpabuf_clear_free(resp);
return eap_peer_tls_build_ack(id, EAP_TYPE_PEAP,
data->peap_version);
}
@@ -1165,9 +1176,13 @@ static Boolean eap_peap_has_reauth_data(struct eap_sm *sm, void *priv)
static void eap_peap_deinit_for_reauth(struct eap_sm *sm, void *priv)
{
struct eap_peap_data *data = priv;
- wpabuf_free(data->pending_phase2_req);
+
+ if (data->phase2_priv && data->phase2_method &&
+ data->phase2_method->deinit_for_reauth)
+ data->phase2_method->deinit_for_reauth(sm, data->phase2_priv);
+ wpabuf_clear_free(data->pending_phase2_req);
data->pending_phase2_req = NULL;
- wpabuf_free(data->pending_resp);
+ wpabuf_clear_free(data->pending_resp);
data->pending_resp = NULL;
data->crypto_binding_used = 0;
}
@@ -1254,6 +1269,7 @@ static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len)
os_memcpy(key, csk, EAP_TLS_KEY_LEN);
wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key",
key, EAP_TLS_KEY_LEN);
+ os_memset(csk, 0, sizeof(csk));
} else
os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN);
@@ -1261,6 +1277,29 @@ static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len)
}
+static u8 * eap_peap_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
+{
+ struct eap_peap_data *data = priv;
+ u8 *key;
+
+ if (!data->key_data || !data->phase2_success)
+ return NULL;
+
+ if (data->crypto_binding_used) {
+ /* [MS-PEAP] does not define EMSK derivation */
+ return NULL;
+ }
+
+ key = os_memdup(data->key_data + EAP_TLS_KEY_LEN, EAP_EMSK_LEN);
+ if (!key)
+ return NULL;
+
+ *len = EAP_EMSK_LEN;
+
+ return key;
+}
+
+
static u8 * eap_peap_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
{
struct eap_peap_data *data = priv;
@@ -1269,12 +1308,11 @@ static u8 * eap_peap_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
if (data->session_id == NULL || !data->phase2_success)
return NULL;
- id = os_malloc(data->id_len);
+ id = os_memdup(data->session_id, data->id_len);
if (id == NULL)
return NULL;
*len = data->id_len;
- os_memcpy(id, data->session_id, data->id_len);
return id;
}
@@ -1294,6 +1332,7 @@ int eap_peer_peap_register(void)
eap->process = eap_peap_process;
eap->isKeyAvailable = eap_peap_isKeyAvailable;
eap->getKey = eap_peap_getKey;
+ eap->get_emsk = eap_peap_get_emsk;
eap->get_status = eap_peap_get_status;
eap->has_reauth_data = eap_peap_has_reauth_data;
eap->deinit_for_reauth = eap_peap_deinit_for_reauth;
diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_proxy.h b/freebsd/contrib/wpa/src/eap_peer/eap_proxy.h
index 23cdbe69..9d8e5702 100644
--- a/freebsd/contrib/wpa/src/eap_peer/eap_proxy.h
+++ b/freebsd/contrib/wpa/src/eap_peer/eap_proxy.h
@@ -20,7 +20,7 @@ enum eap_proxy_status {
};
struct eap_proxy_sm *
-eap_proxy_init(void *eapol_ctx, struct eapol_callbacks *eapol_cb,
+eap_proxy_init(void *eapol_ctx, const struct eapol_callbacks *eapol_cb,
void *msg_ctx);
void eap_proxy_deinit(struct eap_proxy_sm *eap_proxy);
@@ -40,10 +40,16 @@ eap_proxy_packet_update(struct eap_proxy_sm *eap_proxy, u8 *eapReqData,
int eap_proxy_sm_get_status(struct eap_proxy_sm *sm, char *buf, size_t buflen,
int verbose);
-int eap_proxy_get_imsi(struct eap_proxy_sm *eap_proxy, char *imsi_buf,
- size_t *imsi_len);
+int eap_proxy_get_imsi(struct eap_proxy_sm *eap_proxy, int sim_num,
+ char *imsi_buf, size_t *imsi_len);
int eap_proxy_notify_config(struct eap_proxy_sm *sm,
struct eap_peer_config *config);
+u8 * eap_proxy_get_eap_session_id(struct eap_proxy_sm *sm, size_t *len);
+
+u8 * eap_proxy_get_emsk(struct eap_proxy_sm *sm, size_t *len);
+
+void eap_proxy_sm_abort(struct eap_proxy_sm *sm);
+
#endif /* EAP_PROXY_H */
diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_psk.c b/freebsd/contrib/wpa/src/eap_peer/eap_psk.c
index 49ed1736..02066544 100644
--- a/freebsd/contrib/wpa/src/eap_peer/eap_psk.c
+++ b/freebsd/contrib/wpa/src/eap_peer/eap_psk.c
@@ -118,14 +118,13 @@ static struct wpabuf * eap_psk_process_1(struct eap_psk_data *data,
os_memcpy(data->rand_s, hdr1->rand_s, EAP_PSK_RAND_LEN);
os_free(data->id_s);
data->id_s_len = len - sizeof(*hdr1);
- data->id_s = os_malloc(data->id_s_len);
+ data->id_s = os_memdup(hdr1 + 1, data->id_s_len);
if (data->id_s == NULL) {
wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory for "
"ID_S (len=%lu)", (unsigned long) data->id_s_len);
ret->ignore = TRUE;
return NULL;
}
- os_memcpy(data->id_s, (u8 *) (hdr1 + 1), data->id_s_len);
wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: ID_S",
data->id_s, data->id_s_len);
@@ -275,13 +274,12 @@ static struct wpabuf * eap_psk_process_3(struct eap_psk_data *data,
wpabuf_head(reqData), 5);
wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - cipher msg", msg, left);
- decrypted = os_malloc(left);
+ decrypted = os_memdup(msg, left);
if (decrypted == NULL) {
ret->methodState = METHOD_DONE;
ret->decision = DECISION_FAIL;
return NULL;
}
- os_memcpy(decrypted, msg, left);
if (aes_128_eax_decrypt(data->tek, nonce, sizeof(nonce),
wpabuf_head(reqData),
@@ -427,12 +425,11 @@ static u8 * eap_psk_getKey(struct eap_sm *sm, void *priv, size_t *len)
if (data->state != PSK_DONE)
return NULL;
- key = os_malloc(EAP_MSK_LEN);
+ key = os_memdup(data->msk, EAP_MSK_LEN);
if (key == NULL)
return NULL;
*len = EAP_MSK_LEN;
- os_memcpy(key, data->msk, EAP_MSK_LEN);
return key;
}
@@ -468,12 +465,11 @@ static u8 * eap_psk_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
if (data->state != PSK_DONE)
return NULL;
- key = os_malloc(EAP_EMSK_LEN);
+ key = os_memdup(data->emsk, EAP_EMSK_LEN);
if (key == NULL)
return NULL;
*len = EAP_EMSK_LEN;
- os_memcpy(key, data->emsk, EAP_EMSK_LEN);
return key;
}
diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_tls.c b/freebsd/contrib/wpa/src/eap_peer/eap_tls.c
index 35afcf77..37d7f57f 100644
--- a/freebsd/contrib/wpa/src/eap_peer/eap_tls.c
+++ b/freebsd/contrib/wpa/src/eap_peer/eap_tls.c
@@ -175,14 +175,32 @@ static struct wpabuf * eap_tls_failure(struct eap_sm *sm,
static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data,
struct eap_method_ret *ret)
{
+ const char *label;
+
wpa_printf(MSG_DEBUG, "EAP-TLS: Done");
- ret->methodState = METHOD_DONE;
- ret->decision = DECISION_UNCOND_SUCC;
+ if (data->ssl.tls_out) {
+ wpa_printf(MSG_DEBUG, "EAP-TLS: Fragment(s) remaining");
+ return;
+ }
+
+ if (data->ssl.tls_v13) {
+ label = "EXPORTER_EAP_TLS_Key_Material";
+
+ /* A possible NewSessionTicket may be received before
+ * EAP-Success, so need to allow it to be received. */
+ ret->methodState = METHOD_MAY_CONT;
+ ret->decision = DECISION_COND_SUCC;
+ } else {
+ label = "client EAP encryption";
+
+ ret->methodState = METHOD_DONE;
+ ret->decision = DECISION_UNCOND_SUCC;
+ }
eap_tls_free_key(data);
- data->key_data = eap_peer_tls_derive_key(sm, &data->ssl,
- "client EAP encryption",
+ data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, label,
+ NULL, 0,
EAP_TLS_KEY_LEN +
EAP_EMSK_LEN);
if (data->key_data) {
@@ -340,12 +358,11 @@ static u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len)
if (data->key_data == NULL)
return NULL;
- key = os_malloc(EAP_TLS_KEY_LEN);
+ key = os_memdup(data->key_data, EAP_TLS_KEY_LEN);
if (key == NULL)
return NULL;
*len = EAP_TLS_KEY_LEN;
- os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN);
return key;
}
@@ -359,12 +376,11 @@ static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
if (data->key_data == NULL)
return NULL;
- key = os_malloc(EAP_EMSK_LEN);
+ key = os_memdup(data->key_data + EAP_TLS_KEY_LEN, EAP_EMSK_LEN);
if (key == NULL)
return NULL;
*len = EAP_EMSK_LEN;
- os_memcpy(key, data->key_data + EAP_TLS_KEY_LEN, EAP_EMSK_LEN);
return key;
}
@@ -378,12 +394,11 @@ static u8 * eap_tls_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
if (data->session_id == NULL)
return NULL;
- id = os_malloc(data->id_len);
+ id = os_memdup(data->session_id, data->id_len);
if (id == NULL)
return NULL;
*len = data->id_len;
- os_memcpy(id, data->session_id, data->id_len);
return id;
}
diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_tls_common.c b/freebsd/contrib/wpa/src/eap_peer/eap_tls_common.c
index 8908dc2f..d8b0f47f 100644
--- a/freebsd/contrib/wpa/src/eap_peer/eap_tls_common.c
+++ b/freebsd/contrib/wpa/src/eap_peer/eap_tls_common.c
@@ -2,7 +2,7 @@
/*
* EAP peer: EAP-TLS/PEAP/TTLS/FAST common functions
- * Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -72,34 +72,53 @@ static void eap_tls_params_flags(struct tls_connection_params *params,
params->flags &= ~TLS_CONN_DISABLE_SESSION_TICKET;
if (os_strstr(txt, "tls_disable_tlsv1_0=1"))
params->flags |= TLS_CONN_DISABLE_TLSv1_0;
- if (os_strstr(txt, "tls_disable_tlsv1_0=0"))
+ if (os_strstr(txt, "tls_disable_tlsv1_0=0")) {
params->flags &= ~TLS_CONN_DISABLE_TLSv1_0;
+ params->flags |= TLS_CONN_ENABLE_TLSv1_0;
+ }
if (os_strstr(txt, "tls_disable_tlsv1_1=1"))
params->flags |= TLS_CONN_DISABLE_TLSv1_1;
- if (os_strstr(txt, "tls_disable_tlsv1_1=0"))
+ if (os_strstr(txt, "tls_disable_tlsv1_1=0")) {
params->flags &= ~TLS_CONN_DISABLE_TLSv1_1;
+ params->flags |= TLS_CONN_ENABLE_TLSv1_1;
+ }
if (os_strstr(txt, "tls_disable_tlsv1_2=1"))
params->flags |= TLS_CONN_DISABLE_TLSv1_2;
- if (os_strstr(txt, "tls_disable_tlsv1_2=0"))
+ if (os_strstr(txt, "tls_disable_tlsv1_2=0")) {
params->flags &= ~TLS_CONN_DISABLE_TLSv1_2;
+ params->flags |= TLS_CONN_ENABLE_TLSv1_2;
+ }
+ if (os_strstr(txt, "tls_disable_tlsv1_3=1"))
+ params->flags |= TLS_CONN_DISABLE_TLSv1_3;
+ if (os_strstr(txt, "tls_disable_tlsv1_3=0"))
+ params->flags &= ~TLS_CONN_DISABLE_TLSv1_3;
if (os_strstr(txt, "tls_ext_cert_check=1"))
params->flags |= TLS_CONN_EXT_CERT_CHECK;
if (os_strstr(txt, "tls_ext_cert_check=0"))
params->flags &= ~TLS_CONN_EXT_CERT_CHECK;
+ if (os_strstr(txt, "tls_suiteb=1"))
+ params->flags |= TLS_CONN_SUITEB;
+ if (os_strstr(txt, "tls_suiteb=0"))
+ params->flags &= ~TLS_CONN_SUITEB;
+ if (os_strstr(txt, "tls_suiteb_no_ecdh=1"))
+ params->flags |= TLS_CONN_SUITEB_NO_ECDH;
+ if (os_strstr(txt, "tls_suiteb_no_ecdh=0"))
+ params->flags &= ~TLS_CONN_SUITEB_NO_ECDH;
}
static void eap_tls_params_from_conf1(struct tls_connection_params *params,
struct eap_peer_config *config)
{
- params->ca_cert = (char *) config->ca_cert;
- params->ca_path = (char *) config->ca_path;
- params->client_cert = (char *) config->client_cert;
- params->private_key = (char *) config->private_key;
- params->private_key_passwd = (char *) config->private_key_passwd;
- params->dh_file = (char *) config->dh_file;
- params->subject_match = (char *) config->subject_match;
- params->altsubject_match = (char *) config->altsubject_match;
+ params->ca_cert = config->ca_cert;
+ params->ca_path = config->ca_path;
+ params->client_cert = config->client_cert;
+ params->private_key = config->private_key;
+ params->private_key_passwd = config->private_key_passwd;
+ params->dh_file = config->dh_file;
+ params->subject_match = config->subject_match;
+ params->altsubject_match = config->altsubject_match;
+ params->check_cert_subject = config->check_cert_subject;
params->suffix_match = config->domain_suffix_match;
params->domain_match = config->domain_match;
params->engine = config->engine;
@@ -115,14 +134,15 @@ static void eap_tls_params_from_conf1(struct tls_connection_params *params,
static void eap_tls_params_from_conf2(struct tls_connection_params *params,
struct eap_peer_config *config)
{
- params->ca_cert = (char *) config->ca_cert2;
- params->ca_path = (char *) config->ca_path2;
- params->client_cert = (char *) config->client_cert2;
- params->private_key = (char *) config->private_key2;
- params->private_key_passwd = (char *) config->private_key2_passwd;
- params->dh_file = (char *) config->dh_file2;
- params->subject_match = (char *) config->subject_match2;
- params->altsubject_match = (char *) config->altsubject_match2;
+ params->ca_cert = config->ca_cert2;
+ params->ca_path = config->ca_path2;
+ params->client_cert = config->client_cert2;
+ params->private_key = config->private_key2;
+ params->private_key_passwd = config->private_key2_passwd;
+ params->dh_file = config->dh_file2;
+ params->subject_match = config->subject_match2;
+ params->altsubject_match = config->altsubject_match2;
+ params->check_cert_subject = config->check_cert_subject2;
params->suffix_match = config->domain_suffix_match2;
params->domain_match = config->domain_match2;
params->engine = config->engine2;
@@ -153,6 +173,25 @@ static int eap_tls_params_from_conf(struct eap_sm *sm,
*/
params->flags |= TLS_CONN_DISABLE_SESSION_TICKET;
}
+ if (data->eap_type == EAP_TYPE_FAST ||
+ data->eap_type == EAP_TYPE_TTLS ||
+ data->eap_type == EAP_TYPE_PEAP) {
+ /* The current EAP peer implementation is not yet ready for the
+ * TLS v1.3 changes, so disable this by default for now. */
+ params->flags |= TLS_CONN_DISABLE_TLSv1_3;
+ }
+ if (data->eap_type == EAP_TYPE_TLS ||
+ data->eap_type == EAP_UNAUTH_TLS_TYPE ||
+ data->eap_type == EAP_WFA_UNAUTH_TLS_TYPE) {
+ /* While the current EAP-TLS implementation is more or less
+ * complete for TLS v1.3, there has been no interoperability
+ * testing with other implementations, so disable for by default
+ * for now until there has been chance to confirm that no
+ * significant interoperability issues show up with TLS version
+ * update.
+ */
+ params->flags |= TLS_CONN_DISABLE_TLSv1_3;
+ }
if (phase2) {
wpa_printf(MSG_DEBUG, "TLS: using phase2 config options");
eap_tls_params_from_conf2(params, config);
@@ -312,6 +351,8 @@ void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
* @data: Data for TLS processing
* @label: Label string for deriving the keys, e.g., "client EAP encryption"
+ * @context: Optional extra upper-layer context (max len 2^16)
+ * @context_len: The length of the context value
* @len: Length of the key material to generate (usually 64 for MSK)
* Returns: Pointer to allocated key on success or %NULL on failure
*
@@ -320,9 +361,12 @@ void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
* different label to bind the key usage into the generated material.
*
* The caller is responsible for freeing the returned buffer.
+ *
+ * Note: To provide the RFC 5705 context, the context variable must be non-NULL.
*/
u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
- const char *label, size_t len)
+ const char *label, const u8 *context,
+ size_t context_len, size_t len)
{
u8 *out;
@@ -330,8 +374,8 @@ u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
if (out == NULL)
return NULL;
- if (tls_connection_export_key(data->ssl_ctx, data->conn, label, out,
- len)) {
+ if (tls_connection_export_key(data->ssl_ctx, data->conn, label,
+ context, context_len, out, len)) {
os_free(out);
return NULL;
}
@@ -360,6 +404,29 @@ u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm,
struct tls_random keys;
u8 *out;
+ if (eap_type == EAP_TYPE_TLS && data->tls_v13) {
+ u8 *id, *method_id;
+
+ /* Session-Id = <EAP-Type> || Method-Id
+ * Method-Id = TLS-Exporter("EXPORTER_EAP_TLS_Method-Id",
+ * "", 64)
+ */
+ *len = 1 + 64;
+ id = os_malloc(*len);
+ if (!id)
+ return NULL;
+ method_id = eap_peer_tls_derive_key(
+ sm, data, "EXPORTER_EAP_TLS_Method-Id", NULL, 0, 64);
+ if (!method_id) {
+ os_free(id);
+ return NULL;
+ }
+ id[0] = eap_type;
+ os_memcpy(id + 1, method_id, 64);
+ os_free(method_id);
+ return id;
+ }
+
if (tls_connection_get_random(sm->ssl_ctx, data->conn, &keys) ||
keys.client_random == NULL || keys.server_random == NULL)
return NULL;
@@ -663,6 +730,8 @@ int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data,
* the AS.
*/
int res = eap_tls_process_input(sm, data, in_data, out_data);
+ char buf[20];
+
if (res) {
/*
* Input processing failed (res = -1) or more data is
@@ -675,6 +744,12 @@ int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data,
* The incoming message has been reassembled and processed. The
* response was allocated into data->tls_out buffer.
*/
+
+ if (tls_get_version(data->ssl_ctx, data->conn,
+ buf, sizeof(buf)) == 0) {
+ wpa_printf(MSG_DEBUG, "SSL: Using TLS version %s", buf);
+ data->tls_v13 = os_strcmp(buf, "TLSv1.3") == 0;
+ }
}
if (data->tls_out == NULL) {
diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_tls_common.h b/freebsd/contrib/wpa/src/eap_peer/eap_tls_common.h
index acd2b783..5f825294 100644
--- a/freebsd/contrib/wpa/src/eap_peer/eap_tls_common.h
+++ b/freebsd/contrib/wpa/src/eap_peer/eap_tls_common.h
@@ -73,6 +73,11 @@ struct eap_ssl_data {
* eap_type - EAP method used in Phase 1 (EAP_TYPE_TLS/PEAP/TTLS/FAST)
*/
u8 eap_type;
+
+ /**
+ * tls_v13 - Whether TLS v1.3 or newer is used
+ */
+ int tls_v13;
};
@@ -94,7 +99,8 @@ int eap_peer_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
struct eap_peer_config *config, u8 eap_type);
void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data);
u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
- const char *label, size_t len);
+ const char *label, const u8 *context,
+ size_t context_len, size_t len);
u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm,
struct eap_ssl_data *data, u8 eap_type,
size_t *len);
diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_ttls.c b/freebsd/contrib/wpa/src/eap_peer/eap_ttls.c
index f9601e45..9376e2bc 100644
--- a/freebsd/contrib/wpa/src/eap_peer/eap_ttls.c
+++ b/freebsd/contrib/wpa/src/eap_peer/eap_ttls.c
@@ -198,8 +198,8 @@ static void eap_ttls_deinit(struct eap_sm *sm, void *priv)
eap_peer_tls_ssl_deinit(sm, &data->ssl);
eap_ttls_free_key(data);
os_free(data->session_id);
- wpabuf_free(data->pending_phase2_req);
- wpabuf_free(data->pending_resp);
+ wpabuf_clear_free(data->pending_phase2_req);
+ wpabuf_clear_free(data->pending_resp);
os_free(data);
}
@@ -250,7 +250,7 @@ static int eap_ttls_avp_encapsulate(struct wpabuf **resp, u32 avp_code,
msg = wpabuf_alloc(sizeof(struct ttls_avp) + wpabuf_len(*resp) + 4);
if (msg == NULL) {
- wpabuf_free(*resp);
+ wpabuf_clear_free(*resp);
*resp = NULL;
return -1;
}
@@ -260,7 +260,7 @@ static int eap_ttls_avp_encapsulate(struct wpabuf **resp, u32 avp_code,
os_memcpy(pos, wpabuf_head(*resp), wpabuf_len(*resp));
pos += wpabuf_len(*resp);
AVP_PAD(avp, pos);
- wpabuf_free(*resp);
+ wpabuf_clear_free(*resp);
wpabuf_put(msg, pos - avp);
*resp = msg;
return 0;
@@ -273,6 +273,7 @@ static int eap_ttls_v0_derive_key(struct eap_sm *sm,
eap_ttls_free_key(data);
data->key_data = eap_peer_tls_derive_key(sm, &data->ssl,
"ttls keying material",
+ NULL, 0,
EAP_TLS_KEY_LEN +
EAP_EMSK_LEN);
if (!data->key_data) {
@@ -305,7 +306,8 @@ static int eap_ttls_v0_derive_key(struct eap_sm *sm,
static u8 * eap_ttls_implicit_challenge(struct eap_sm *sm,
struct eap_ttls_data *data, size_t len)
{
- return eap_peer_tls_derive_key(sm, &data->ssl, "ttls challenge", len);
+ return eap_peer_tls_derive_key(sm, &data->ssl, "ttls challenge",
+ NULL, 0, len);
}
#endif /* CONFIG_FIPS */
@@ -460,7 +462,7 @@ static int eap_ttls_phase2_request_eap(struct eap_sm *sm,
if (*resp == NULL &&
(config->pending_req_identity || config->pending_req_password ||
- config->pending_req_otp)) {
+ config->pending_req_otp || config->pending_req_sim)) {
return 0;
}
@@ -512,7 +514,7 @@ static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm,
challenge = eap_ttls_implicit_challenge(
sm, data, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 1);
if (challenge == NULL) {
- wpabuf_free(msg);
+ wpabuf_clear_free(msg);
wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive "
"implicit challenge");
return -1;
@@ -531,7 +533,7 @@ static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm,
*pos++ = 0; /* Flags */
if (os_get_random(pos, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN) < 0) {
os_free(challenge);
- wpabuf_free(msg);
+ wpabuf_clear_free(msg);
wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to get "
"random data for peer challenge");
return -1;
@@ -545,7 +547,7 @@ static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm,
peer_challenge, pos, data->auth_response,
data->master_key)) {
os_free(challenge);
- wpabuf_free(msg);
+ wpabuf_clear_free(msg);
wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive "
"response");
return -1;
@@ -606,7 +608,7 @@ static int eap_ttls_phase2_request_mschap(struct eap_sm *sm,
challenge = eap_ttls_implicit_challenge(
sm, data, EAP_TTLS_MSCHAP_CHALLENGE_LEN + 1);
if (challenge == NULL) {
- wpabuf_free(msg);
+ wpabuf_clear_free(msg);
wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAP: Failed to derive "
"implicit challenge");
return -1;
@@ -626,12 +628,28 @@ static int eap_ttls_phase2_request_mschap(struct eap_sm *sm,
os_memset(pos, 0, 24); /* LM-Response */
pos += 24;
if (pwhash) {
- challenge_response(challenge, password, pos); /* NT-Response */
+ /* NT-Response */
+ if (challenge_response(challenge, password, pos)) {
+ wpa_printf(MSG_ERROR,
+ "EAP-TTLS/MSCHAP: Failed derive password hash");
+ wpabuf_clear_free(msg);
+ os_free(challenge);
+ return -1;
+ }
+
wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: MSCHAP password hash",
password, 16);
} else {
- nt_challenge_response(challenge, password, password_len,
- pos); /* NT-Response */
+ /* NT-Response */
+ if (nt_challenge_response(challenge, password, password_len,
+ pos)) {
+ wpa_printf(MSG_ERROR,
+ "EAP-TTLS/MSCHAP: Failed derive password");
+ wpabuf_clear_free(msg);
+ os_free(challenge);
+ return -1;
+ }
+
wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: MSCHAP password",
password, password_len);
}
@@ -746,7 +764,7 @@ static int eap_ttls_phase2_request_chap(struct eap_sm *sm,
challenge = eap_ttls_implicit_challenge(
sm, data, EAP_TTLS_CHAP_CHALLENGE_LEN + 1);
if (challenge == NULL) {
- wpabuf_free(msg);
+ wpabuf_clear_free(msg);
wpa_printf(MSG_ERROR, "EAP-TTLS/CHAP: Failed to derive "
"implicit challenge");
return -1;
@@ -872,13 +890,12 @@ static int eap_ttls_parse_attr_eap(const u8 *dpos, size_t dlen,
{
wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP - EAP Message");
if (parse->eapdata == NULL) {
- parse->eapdata = os_malloc(dlen);
+ parse->eapdata = os_memdup(dpos, dlen);
if (parse->eapdata == NULL) {
wpa_printf(MSG_WARNING, "EAP-TTLS: Failed to allocate "
"memory for Phase 2 EAP data");
return -1;
}
- os_memcpy(parse->eapdata, dpos, dlen);
parse->eap_len = dlen;
} else {
u8 *neweap = os_realloc(parse->eapdata, parse->eap_len + dlen);
@@ -1060,10 +1077,10 @@ static int eap_ttls_encrypt_response(struct eap_sm *sm,
resp, out_data)) {
wpa_printf(MSG_INFO, "EAP-TTLS: Failed to encrypt a Phase 2 "
"frame");
- wpabuf_free(resp);
+ wpabuf_clear_free(resp);
return -1;
}
- wpabuf_free(resp);
+ wpabuf_clear_free(resp);
return 0;
}
@@ -1282,8 +1299,9 @@ static int eap_ttls_process_decrypted(struct eap_sm *sm,
} else if (config->pending_req_identity ||
config->pending_req_password ||
config->pending_req_otp ||
- config->pending_req_new_password) {
- wpabuf_free(data->pending_phase2_req);
+ config->pending_req_new_password ||
+ config->pending_req_sim) {
+ wpabuf_clear_free(data->pending_phase2_req);
data->pending_phase2_req = wpabuf_dup(in_decrypted);
}
@@ -1319,13 +1337,14 @@ static int eap_ttls_implicit_identity_request(struct eap_sm *sm,
(config->pending_req_identity ||
config->pending_req_password ||
config->pending_req_otp ||
- config->pending_req_new_password)) {
+ config->pending_req_new_password ||
+ config->pending_req_sim)) {
/*
* Use empty buffer to force implicit request
* processing when EAP request is re-processed after
* user input.
*/
- wpabuf_free(data->pending_phase2_req);
+ wpabuf_clear_free(data->pending_phase2_req);
data->pending_phase2_req = wpabuf_alloc(0);
}
@@ -1398,7 +1417,7 @@ static int eap_ttls_decrypt(struct eap_sm *sm, struct eap_ttls_data *data,
in_decrypted = data->pending_phase2_req;
data->pending_phase2_req = NULL;
if (wpabuf_len(in_decrypted) == 0) {
- wpabuf_free(in_decrypted);
+ wpabuf_clear_free(in_decrypted);
return eap_ttls_implicit_identity_request(
sm, data, ret, identifier, out_data);
}
@@ -1434,7 +1453,7 @@ continue_req:
&parse, in_decrypted, out_data);
done:
- wpabuf_free(in_decrypted);
+ wpabuf_clear_free(in_decrypted);
os_free(parse.eapdata);
if (retval < 0) {
@@ -1494,7 +1513,7 @@ static int eap_ttls_process_handshake(struct eap_sm *sm,
if (sm->waiting_ext_cert_check) {
wpa_printf(MSG_DEBUG,
"EAP-TTLS: Waiting external server certificate validation");
- wpabuf_free(data->pending_resp);
+ wpabuf_clear_free(data->pending_resp);
data->pending_resp = *out_data;
*out_data = NULL;
return 0;
@@ -1528,7 +1547,7 @@ static int eap_ttls_process_handshake(struct eap_sm *sm,
/*
* Application data included in the handshake message.
*/
- wpabuf_free(data->pending_phase2_req);
+ wpabuf_clear_free(data->pending_phase2_req);
data->pending_phase2_req = *out_data;
*out_data = NULL;
res = eap_ttls_decrypt(sm, data, ret, identifier, in_data,
@@ -1539,7 +1558,7 @@ static int eap_ttls_process_handshake(struct eap_sm *sm,
}
-static void eap_ttls_check_auth_status(struct eap_sm *sm,
+static void eap_ttls_check_auth_status(struct eap_sm *sm,
struct eap_ttls_data *data,
struct eap_method_ret *ret)
{
@@ -1631,7 +1650,7 @@ static struct wpabuf * eap_ttls_process(struct eap_sm *sm, void *priv,
/* FIX: what about res == -1? Could just move all error processing into
* the other functions and get rid of this res==1 case here. */
if (res == 1) {
- wpabuf_free(resp);
+ wpabuf_clear_free(resp);
return eap_peer_tls_build_ack(id, EAP_TYPE_TTLS,
data->ttls_version);
}
@@ -1650,9 +1669,13 @@ static Boolean eap_ttls_has_reauth_data(struct eap_sm *sm, void *priv)
static void eap_ttls_deinit_for_reauth(struct eap_sm *sm, void *priv)
{
struct eap_ttls_data *data = priv;
- wpabuf_free(data->pending_phase2_req);
+
+ if (data->phase2_priv && data->phase2_method &&
+ data->phase2_method->deinit_for_reauth)
+ data->phase2_method->deinit_for_reauth(sm, data->phase2_priv);
+ wpabuf_clear_free(data->pending_phase2_req);
data->pending_phase2_req = NULL;
- wpabuf_free(data->pending_resp);
+ wpabuf_clear_free(data->pending_resp);
data->pending_resp = NULL;
data->decision_succ = DECISION_FAIL;
#ifdef EAP_TNC
@@ -1741,12 +1764,11 @@ static u8 * eap_ttls_getKey(struct eap_sm *sm, void *priv, size_t *len)
if (data->key_data == NULL || !data->phase2_success)
return NULL;
- key = os_malloc(EAP_TLS_KEY_LEN);
+ key = os_memdup(data->key_data, EAP_TLS_KEY_LEN);
if (key == NULL)
return NULL;
*len = EAP_TLS_KEY_LEN;
- os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN);
return key;
}
@@ -1760,12 +1782,11 @@ static u8 * eap_ttls_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
if (data->session_id == NULL || !data->phase2_success)
return NULL;
- id = os_malloc(data->id_len);
+ id = os_memdup(data->session_id, data->id_len);
if (id == NULL)
return NULL;
*len = data->id_len;
- os_memcpy(id, data->session_id, data->id_len);
return id;
}
@@ -1779,12 +1800,11 @@ static u8 * eap_ttls_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
if (data->key_data == NULL)
return NULL;
- key = os_malloc(EAP_EMSK_LEN);
+ key = os_memdup(data->key_data + EAP_TLS_KEY_LEN, EAP_EMSK_LEN);
if (key == NULL)
return NULL;
*len = EAP_EMSK_LEN;
- os_memcpy(key, data->key_data + EAP_TLS_KEY_LEN, EAP_EMSK_LEN);
return key;
}
diff --git a/freebsd/contrib/wpa/src/eapol_auth/eapol_auth_sm.h b/freebsd/contrib/wpa/src/eapol_auth/eapol_auth_sm.h
index e1974e43..44f3f31c 100644
--- a/freebsd/contrib/wpa/src/eapol_auth/eapol_auth_sm.h
+++ b/freebsd/contrib/wpa/src/eapol_auth/eapol_auth_sm.h
@@ -28,6 +28,7 @@ struct eapol_auth_config {
char *erp_domain; /* a copy of this will be allocated */
int erp; /* Whether ERP is enabled on authentication server */
unsigned int tls_session_lifetime;
+ unsigned int tls_flags;
u8 *pac_opaque_encr_key;
u8 *eap_fast_a_id;
size_t eap_fast_a_id_len;
diff --git a/freebsd/contrib/wpa/src/eapol_supp/eapol_supp_sm.c b/freebsd/contrib/wpa/src/eapol_supp/eapol_supp_sm.c
index 938e0d05..c69f815e 100644
--- a/freebsd/contrib/wpa/src/eapol_supp/eapol_supp_sm.c
+++ b/freebsd/contrib/wpa/src/eapol_supp/eapol_supp_sm.c
@@ -18,6 +18,7 @@
#include "crypto/md5.h"
#include "common/eapol_common.h"
#include "eap_peer/eap.h"
+#include "eap_peer/eap_config.h"
#include "eap_peer/eap_proxy.h"
#include "eapol_supp_sm.h"
@@ -97,7 +98,7 @@ struct eapol_sm {
SUPP_BE_RECEIVE = 4,
SUPP_BE_RESPONSE = 5,
SUPP_BE_FAIL = 6,
- SUPP_BE_TIMEOUT = 7,
+ SUPP_BE_TIMEOUT = 7,
SUPP_BE_SUCCESS = 8
} SUPP_BE_state; /* dot1xSuppBackendPaeState */
/* Variables */
@@ -190,8 +191,9 @@ static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx)
}
if (sm->authWhile | sm->heldWhile | sm->startWhen | sm->idleWhile) {
- eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx,
- sm);
+ if (eloop_register_timeout(1, 0, eapol_port_timers_tick,
+ eloop_ctx, sm) < 0)
+ sm->timer_tick_enabled = 0;
} else {
wpa_printf(MSG_DEBUG, "EAPOL: disable timer tick");
sm->timer_tick_enabled = 0;
@@ -205,9 +207,9 @@ static void eapol_enable_timer_tick(struct eapol_sm *sm)
if (sm->timer_tick_enabled)
return;
wpa_printf(MSG_DEBUG, "EAPOL: enable timer tick");
- sm->timer_tick_enabled = 1;
eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
- eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm);
+ if (eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm) == 0)
+ sm->timer_tick_enabled = 1;
}
@@ -252,6 +254,8 @@ SM_STATE(SUPP_PAE, CONNECTING)
if (sm->eapTriggerStart)
send_start = 1;
+ if (sm->ctx->preauth)
+ send_start = 1;
sm->eapTriggerStart = FALSE;
if (send_start) {
@@ -492,9 +496,24 @@ SM_STATE(SUPP_BE, SUCCESS)
#ifdef CONFIG_EAP_PROXY
if (sm->use_eap_proxy) {
if (eap_proxy_key_available(sm->eap_proxy)) {
+ u8 *session_id, *emsk;
+ size_t session_id_len, emsk_len;
+
/* New key received - clear IEEE 802.1X EAPOL-Key replay
* counter */
sm->replay_counter_valid = FALSE;
+
+ session_id = eap_proxy_get_eap_session_id(
+ sm->eap_proxy, &session_id_len);
+ emsk = eap_proxy_get_emsk(sm->eap_proxy, &emsk_len);
+ if (sm->config->erp && session_id && emsk) {
+ eap_peer_erp_init(sm->eap, session_id,
+ session_id_len, emsk,
+ emsk_len);
+ } else {
+ os_free(session_id);
+ bin_clear_free(emsk, emsk_len);
+ }
}
return;
}
@@ -899,6 +918,9 @@ static void eapol_sm_abortSupp(struct eapol_sm *sm)
wpabuf_free(sm->eapReqData);
sm->eapReqData = NULL;
eap_sm_abort(sm->eap);
+#ifdef CONFIG_EAP_PROXY
+ eap_proxy_sm_abort(sm->eap_proxy);
+#endif /* CONFIG_EAP_PROXY */
}
@@ -2000,7 +2022,17 @@ static void eapol_sm_notify_status(void *ctx, const char *status,
}
+static void eapol_sm_notify_eap_error(void *ctx, int error_code)
+{
+ struct eapol_sm *sm = ctx;
+
+ if (sm->ctx->eap_error_cb)
+ sm->ctx->eap_error_cb(sm->ctx->ctx, error_code);
+}
+
+
#ifdef CONFIG_EAP_PROXY
+
static void eapol_sm_eap_proxy_cb(void *ctx)
{
struct eapol_sm *sm = ctx;
@@ -2008,6 +2040,18 @@ static void eapol_sm_eap_proxy_cb(void *ctx)
if (sm->ctx->eap_proxy_cb)
sm->ctx->eap_proxy_cb(sm->ctx->ctx);
}
+
+
+static void
+eapol_sm_eap_proxy_notify_sim_status(void *ctx,
+ enum eap_proxy_sim_state sim_state)
+{
+ struct eapol_sm *sm = ctx;
+
+ if (sm->ctx->eap_proxy_notify_sim_status)
+ sm->ctx->eap_proxy_notify_sim_status(sm->ctx->ctx, sim_state);
+}
+
#endif /* CONFIG_EAP_PROXY */
@@ -2034,8 +2078,11 @@ static const struct eapol_callbacks eapol_cb =
eapol_sm_eap_param_needed,
eapol_sm_notify_cert,
eapol_sm_notify_status,
+ eapol_sm_notify_eap_error,
#ifdef CONFIG_EAP_PROXY
eapol_sm_eap_proxy_cb,
+ eapol_sm_eap_proxy_notify_sim_status,
+ eapol_sm_get_eap_proxy_imsi,
#endif /* CONFIG_EAP_PROXY */
eapol_sm_set_anon_id
};
@@ -2097,8 +2144,8 @@ struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx)
sm->initialize = FALSE;
eapol_sm_step(sm);
- sm->timer_tick_enabled = 1;
- eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm);
+ if (eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm) == 0)
+ sm->timer_tick_enabled = 1;
return sm;
}
@@ -2143,16 +2190,16 @@ int eapol_sm_failed(struct eapol_sm *sm)
}
-int eapol_sm_get_eap_proxy_imsi(struct eapol_sm *sm, char *imsi, size_t *len)
-{
#ifdef CONFIG_EAP_PROXY
+int eapol_sm_get_eap_proxy_imsi(void *ctx, int sim_num, char *imsi, size_t *len)
+{
+ struct eapol_sm *sm = ctx;
+
if (sm->eap_proxy == NULL)
return -1;
- return eap_proxy_get_imsi(sm->eap_proxy, imsi, len);
-#else /* CONFIG_EAP_PROXY */
- return -1;
-#endif /* CONFIG_EAP_PROXY */
+ return eap_proxy_get_imsi(sm->eap_proxy, sim_num, imsi, len);
}
+#endif /* CONFIG_EAP_PROXY */
void eapol_sm_erp_flush(struct eapol_sm *sm)
@@ -2160,3 +2207,56 @@ void eapol_sm_erp_flush(struct eapol_sm *sm)
if (sm)
eap_peer_erp_free_keys(sm->eap);
}
+
+
+struct wpabuf * eapol_sm_build_erp_reauth_start(struct eapol_sm *sm)
+{
+#ifdef CONFIG_ERP
+ if (!sm)
+ return NULL;
+ return eap_peer_build_erp_reauth_start(sm->eap, 0);
+#else /* CONFIG_ERP */
+ return NULL;
+#endif /* CONFIG_ERP */
+}
+
+
+void eapol_sm_process_erp_finish(struct eapol_sm *sm, const u8 *buf,
+ size_t len)
+{
+#ifdef CONFIG_ERP
+ if (!sm)
+ return;
+ eap_peer_finish(sm->eap, (const struct eap_hdr *) buf, len);
+#endif /* CONFIG_ERP */
+}
+
+
+int eapol_sm_update_erp_next_seq_num(struct eapol_sm *sm, u16 next_seq_num)
+{
+#ifdef CONFIG_ERP
+ if (!sm)
+ return -1;
+ return eap_peer_update_erp_next_seq_num(sm->eap, next_seq_num);
+#else /* CONFIG_ERP */
+ return -1;
+#endif /* CONFIG_ERP */
+}
+
+
+int eapol_sm_get_erp_info(struct eapol_sm *sm, struct eap_peer_config *config,
+ const u8 **username, size_t *username_len,
+ const u8 **realm, size_t *realm_len,
+ u16 *erp_next_seq_num, const u8 **rrk,
+ size_t *rrk_len)
+{
+#ifdef CONFIG_ERP
+ if (!sm)
+ return -1;
+ return eap_peer_get_erp_info(sm->eap, config, username, username_len,
+ realm, realm_len, erp_next_seq_num, rrk,
+ rrk_len);
+#else /* CONFIG_ERP */
+ return -1;
+#endif /* CONFIG_ERP */
+}
diff --git a/freebsd/contrib/wpa/src/eapol_supp/eapol_supp_sm.h b/freebsd/contrib/wpa/src/eapol_supp/eapol_supp_sm.h
index 1309ff75..74f40bb1 100644
--- a/freebsd/contrib/wpa/src/eapol_supp/eapol_supp_sm.h
+++ b/freebsd/contrib/wpa/src/eapol_supp/eapol_supp_sm.h
@@ -271,12 +271,27 @@ struct eapol_ctx {
void (*status_cb)(void *ctx, const char *status,
const char *parameter);
+ /**
+ * eap_error_cb - Notification of EAP method error
+ * @ctx: Callback context (ctx)
+ * @error_code: EAP method error code
+ */
+ void (*eap_error_cb)(void *ctx, int error_code);
+
#ifdef CONFIG_EAP_PROXY
/**
* eap_proxy_cb - Callback signifying any updates from eap_proxy
* @ctx: eapol_ctx from eap_peer_sm_init() call
*/
void (*eap_proxy_cb)(void *ctx);
+
+ /**
+ * eap_proxy_notify_sim_status - Notification of SIM status change
+ * @ctx: eapol_ctx from eap_peer_sm_init() call
+ * @status: One of enum value from sim_state
+ */
+ void (*eap_proxy_notify_sim_status)(void *ctx,
+ enum eap_proxy_sim_state sim_state);
#endif /* CONFIG_EAP_PROXY */
/**
@@ -328,7 +343,18 @@ void eapol_sm_set_ext_pw_ctx(struct eapol_sm *sm,
struct ext_password_data *ext);
int eapol_sm_failed(struct eapol_sm *sm);
void eapol_sm_erp_flush(struct eapol_sm *sm);
-int eapol_sm_get_eap_proxy_imsi(struct eapol_sm *sm, char *imsi, size_t *len);
+struct wpabuf * eapol_sm_build_erp_reauth_start(struct eapol_sm *sm);
+void eapol_sm_process_erp_finish(struct eapol_sm *sm, const u8 *buf,
+ size_t len);
+int eapol_sm_get_eap_proxy_imsi(void *ctx, int sim_num, char *imsi,
+ size_t *len);
+int eapol_sm_update_erp_next_seq_num(struct eapol_sm *sm, u16 next_seq_num);
+int eapol_sm_get_erp_info(struct eapol_sm *sm, struct eap_peer_config *config,
+ const u8 **username, size_t *username_len,
+ const u8 **realm, size_t *realm_len,
+ u16 *erp_next_seq_num, const u8 **rrk,
+ size_t *rrk_len);
+
#else /* IEEE8021X_EAPOL */
static inline struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx)
{
@@ -438,6 +464,28 @@ static inline int eapol_sm_failed(struct eapol_sm *sm)
static inline void eapol_sm_erp_flush(struct eapol_sm *sm)
{
}
+static inline struct wpabuf *
+eapol_sm_build_erp_reauth_start(struct eapol_sm *sm)
+{
+ return NULL;
+}
+static inline void eapol_sm_process_erp_finish(struct eapol_sm *sm,
+ const u8 *buf, size_t len)
+{
+}
+static inline int eapol_sm_update_erp_next_seq_num(struct eapol_sm *sm,
+ u16 next_seq_num)
+{
+ return -1;
+}
+static inline int
+eapol_sm_get_erp_info(struct eapol_sm *sm, struct eap_peer_config *config,
+ const u8 **username, size_t *username_len,
+ const u8 **realm, size_t *realm_len,
+ u16 *erp_next_seq_num, const u8 **rrk, size_t *rrk_len)
+{
+ return -1;
+}
#endif /* IEEE8021X_EAPOL */
#endif /* EAPOL_SUPP_SM_H */
diff --git a/freebsd/contrib/wpa/src/fst/fst.h b/freebsd/contrib/wpa/src/fst/fst.h
index 0c0e435b..29674912 100644
--- a/freebsd/contrib/wpa/src/fst/fst.h
+++ b/freebsd/contrib/wpa/src/fst/fst.h
@@ -19,10 +19,18 @@
#define US_IN_MS 1000
#define LLT_UNIT_US 32 /* See 10.32.2.2 Transitioning between states */
-#define FST_LLT_MS_TO_VAL(m) (((u32) (m)) * US_IN_MS / LLT_UNIT_US)
-#define FST_LLT_VAL_TO_MS(v) (((u32) (v)) * LLT_UNIT_US / US_IN_MS)
-
-#define FST_MAX_LLT_MS FST_LLT_VAL_TO_MS(-1)
+/*
+ * These were originally
+ * #define FST_LLT_MS_TO_VAL(m) (((u32) (m)) * US_IN_MS / LLT_UNIT_US)
+ * #define FST_LLT_VAL_TO_MS(v) (((u32) (v)) * LLT_UNIT_US / US_IN_MS)
+ * #define FST_MAX_LLT_MS FST_LLT_VAL_TO_MS(-1)
+ * but those can overflow 32-bit unsigned integer, so use alternative defines
+ * to avoid undefined behavior with such overflow.
+ * LLT_UNIT_US/US_IN_MS = 32/1000 = 4/125
+ */
+#define FST_LLT_MS_TO_VAL(m) (((u32) (m)) * 125 / 4)
+#define FST_LLT_VAL_TO_MS(v) (((u32) (v)) * 4 / 125)
+#define FST_MAX_LLT_MS (((u32) -1) / 4)
#define FST_MAX_PRIO_VALUE ((u8) -1)
#define FST_MAX_GROUP_ID_LEN IFNAMSIZ
diff --git a/freebsd/contrib/wpa/src/fst/fst_ctrl_aux.h b/freebsd/contrib/wpa/src/fst/fst_ctrl_aux.h
index e2133f50..0aff5d06 100644
--- a/freebsd/contrib/wpa/src/fst/fst_ctrl_aux.h
+++ b/freebsd/contrib/wpa/src/fst/fst_ctrl_aux.h
@@ -35,6 +35,17 @@ enum fst_event_type {
* more info */
};
+enum fst_reason {
+ REASON_TEARDOWN,
+ REASON_SETUP,
+ REASON_SWITCH,
+ REASON_STT,
+ REASON_REJECT,
+ REASON_ERROR_PARAMS,
+ REASON_RESET,
+ REASON_DETACH_IFACE,
+};
+
enum fst_initiator {
FST_INITIATOR_UNDEFINED,
FST_INITIATOR_LOCAL,
@@ -57,16 +68,7 @@ union fst_event_extra {
enum fst_session_state new_state;
union fst_session_state_switch_extra {
struct {
- enum fst_reason {
- REASON_TEARDOWN,
- REASON_SETUP,
- REASON_SWITCH,
- REASON_STT,
- REASON_REJECT,
- REASON_ERROR_PARAMS,
- REASON_RESET,
- REASON_DETACH_IFACE,
- } reason;
+ enum fst_reason reason;
u8 reject_code; /* REASON_REJECT */
/* REASON_SWITCH,
* REASON_TEARDOWN,
diff --git a/freebsd/contrib/wpa/src/l2_packet/l2_packet.h b/freebsd/contrib/wpa/src/l2_packet/l2_packet.h
index 2a452458..53871774 100644
--- a/freebsd/contrib/wpa/src/l2_packet/l2_packet.h
+++ b/freebsd/contrib/wpa/src/l2_packet/l2_packet.h
@@ -42,6 +42,7 @@ struct l2_ethhdr {
enum l2_packet_filter_type {
L2_PACKET_FILTER_DHCP,
L2_PACKET_FILTER_NDISC,
+ L2_PACKET_FILTER_PKTTYPE,
};
/**
diff --git a/freebsd/contrib/wpa/src/p2p/p2p.h b/freebsd/contrib/wpa/src/p2p/p2p.h
index 7b18dcfc..425b037b 100644
--- a/freebsd/contrib/wpa/src/p2p/p2p.h
+++ b/freebsd/contrib/wpa/src/p2p/p2p.h
@@ -104,6 +104,11 @@ struct p2p_go_neg_results {
unsigned int vht_center_freq2;
/**
+ * he - Indicates if IEEE 802.11ax HE is enabled
+ */
+ int he;
+
+ /**
* ssid - SSID of the group
*/
u8 ssid[SSID_MAX_LEN];
@@ -660,6 +665,8 @@ struct p2p_config {
* @buf: Frame body (starting from Category field)
* @len: Length of buf in octets
* @wait_time: How many msec to wait for a response frame
+ * @scheduled: Return value indicating whether the transmissions was
+ * scheduled to happen once the radio is available
* Returns: 0 on success, -1 on failure
*
* The Action frame may not be transmitted immediately and the status
@@ -670,7 +677,7 @@ struct p2p_config {
*/
int (*send_action)(void *ctx, unsigned int freq, const u8 *dst,
const u8 *src, const u8 *bssid, const u8 *buf,
- size_t len, unsigned int wait_time);
+ size_t len, unsigned int wait_time, int *scheduled);
/**
* send_action_done - Notify that Action frame sequence was completed
@@ -2005,6 +2012,8 @@ void p2p_set_managed_oper(struct p2p_data *p2p, int enabled);
* @p2p: P2P config
* @op_class: Selected operating class
* @op_channel: Selected social channel
+ * @avoid_list: Channel ranges to try to avoid or %NULL
+ * @disallow_list: Channel ranges to discard or %NULL
* Returns: 0 on success, -1 on failure
*
* This function is used before p2p_init is called. A random social channel
@@ -2012,7 +2021,9 @@ void p2p_set_managed_oper(struct p2p_data *p2p, int enabled);
* returned on success.
*/
int p2p_config_get_random_social(struct p2p_config *p2p, u8 *op_class,
- u8 *op_channel);
+ u8 *op_channel,
+ struct wpa_freq_range_list *avoid_list,
+ struct wpa_freq_range_list *disallow_list);
int p2p_set_listen_channel(struct p2p_data *p2p, u8 reg_class, u8 channel,
u8 forced);
@@ -2266,6 +2277,7 @@ int p2p_set_wfd_ie_prov_disc_req(struct p2p_data *p2p, struct wpabuf *ie);
int p2p_set_wfd_ie_prov_disc_resp(struct p2p_data *p2p, struct wpabuf *ie);
int p2p_set_wfd_ie_go_neg(struct p2p_data *p2p, struct wpabuf *ie);
int p2p_set_wfd_dev_info(struct p2p_data *p2p, const struct wpabuf *elem);
+int p2p_set_wfd_r2_dev_info(struct p2p_data *p2p, const struct wpabuf *elem);
int p2p_set_wfd_assoc_bssid(struct p2p_data *p2p, const struct wpabuf *elem);
int p2p_set_wfd_coupled_sink_info(struct p2p_data *p2p,
const struct wpabuf *elem);
@@ -2373,6 +2385,8 @@ void p2p_expire_peers(struct p2p_data *p2p);
void p2p_set_own_pref_freq_list(struct p2p_data *p2p,
const unsigned int *pref_freq_list,
unsigned int size);
+void p2p_set_override_pref_op_chan(struct p2p_data *p2p, u8 op_class,
+ u8 chan);
/**
* p2p_group_get_common_freqs - Get the group common frequencies
diff --git a/freebsd/contrib/wpa/src/radius/radius.h b/freebsd/contrib/wpa/src/radius/radius.h
index cd510d2c..630c0f9d 100644
--- a/freebsd/contrib/wpa/src/radius/radius.h
+++ b/freebsd/contrib/wpa/src/radius/radius.h
@@ -102,8 +102,13 @@ enum { RADIUS_ATTR_USER_NAME = 1,
RADIUS_ATTR_EXTENDED_LOCATION_POLICY_RULES = 130,
RADIUS_ATTR_LOCATION_CAPABLE = 131,
RADIUS_ATTR_REQUESTED_LOCATION_INFO = 132,
+ RADIUS_ATTR_GSS_ACCEPTOR_SERVICE_NAME = 164,
+ RADIUS_ATTR_GSS_ACCEPTOR_HOST_NAME = 165,
+ RADIUS_ATTR_GSS_ACCEPTOR_SERVICE_SPECIFICS = 166,
+ RADIUS_ATTR_GSS_ACCEPTOR_REALM_NAME = 167,
RADIUS_ATTR_MOBILITY_DOMAIN_ID = 177,
RADIUS_ATTR_WLAN_HESSID = 181,
+ RADIUS_ATTR_WLAN_REASON_CODE = 185,
RADIUS_ATTR_WLAN_PAIRWISE_CIPHER = 186,
RADIUS_ATTR_WLAN_GROUP_CIPHER = 187,
RADIUS_ATTR_WLAN_AKM_SUITE = 188,
@@ -193,6 +198,11 @@ enum {
RADIUS_VENDOR_ATTR_WFA_HS20_STA_VERSION = 3,
RADIUS_VENDOR_ATTR_WFA_HS20_DEAUTH_REQ = 4,
RADIUS_VENDOR_ATTR_WFA_HS20_SESSION_INFO_URL = 5,
+ RADIUS_VENDOR_ATTR_WFA_HS20_ROAMING_CONSORTIUM = 6,
+ RADIUS_VENDOR_ATTR_WFA_HS20_T_C_FILENAME = 7,
+ RADIUS_VENDOR_ATTR_WFA_HS20_TIMESTAMP = 8,
+ RADIUS_VENDOR_ATTR_WFA_HS20_T_C_FILTERING = 9,
+ RADIUS_VENDOR_ATTR_WFA_HS20_T_C_URL = 10,
};
#ifdef _MSC_VER
diff --git a/freebsd/contrib/wpa/src/rsn_supp/peerkey.c b/freebsd/contrib/wpa/src/rsn_supp/peerkey.c
deleted file mode 100644
index 87263f86..00000000
--- a/freebsd/contrib/wpa/src/rsn_supp/peerkey.c
+++ /dev/null
@@ -1,1157 +0,0 @@
-#include <machine/rtems-bsd-user-space.h>
-
-/*
- * WPA Supplicant - PeerKey for Direct Link Setup (DLS)
- * Copyright (c) 2006-2015, Jouni Malinen <j@w1.fi>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#include "includes.h"
-
-#ifdef CONFIG_PEERKEY
-
-#include "common.h"
-#include "eloop.h"
-#include "crypto/sha1.h"
-#include "crypto/sha256.h"
-#include "crypto/random.h"
-#include "common/ieee802_11_defs.h"
-#include "wpa.h"
-#include "wpa_i.h"
-#include "wpa_ie.h"
-#include "peerkey.h"
-
-
-static u8 * wpa_add_ie(u8 *pos, const u8 *ie, size_t ie_len)
-{
- os_memcpy(pos, ie, ie_len);
- return pos + ie_len;
-}
-
-
-static u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len)
-{
- *pos++ = WLAN_EID_VENDOR_SPECIFIC;
- *pos++ = RSN_SELECTOR_LEN + data_len;
- RSN_SELECTOR_PUT(pos, kde);
- pos += RSN_SELECTOR_LEN;
- os_memcpy(pos, data, data_len);
- pos += data_len;
- return pos;
-}
-
-
-static void wpa_supplicant_smk_timeout(void *eloop_ctx, void *timeout_ctx)
-{
-#if 0
- struct wpa_sm *sm = eloop_ctx;
- struct wpa_peerkey *peerkey = timeout_ctx;
-#endif
- /* TODO: time out SMK and any STK that was generated using this SMK */
-}
-
-
-static void wpa_supplicant_peerkey_free(struct wpa_sm *sm,
- struct wpa_peerkey *peerkey)
-{
- eloop_cancel_timeout(wpa_supplicant_smk_timeout, sm, peerkey);
- os_free(peerkey);
-}
-
-
-static int wpa_supplicant_send_smk_error(struct wpa_sm *sm, const u8 *dst,
- const u8 *peer,
- u16 mui, u16 error_type, int ver)
-{
- size_t rlen;
- struct wpa_eapol_key *err;
- struct wpa_eapol_key_192 *err192;
- struct rsn_error_kde error;
- u8 *rbuf, *pos;
- size_t kde_len;
- u16 key_info;
-
- kde_len = 2 + RSN_SELECTOR_LEN + sizeof(error);
- if (peer)
- kde_len += 2 + RSN_SELECTOR_LEN + ETH_ALEN;
-
- rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY,
- NULL, sizeof(*err) + kde_len, &rlen,
- (void *) &err);
- if (rbuf == NULL)
- return -1;
- err192 = (struct wpa_eapol_key_192 *) err;
-
- err->type = EAPOL_KEY_TYPE_RSN;
- key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC |
- WPA_KEY_INFO_SECURE | WPA_KEY_INFO_ERROR |
- WPA_KEY_INFO_REQUEST;
- WPA_PUT_BE16(err->key_info, key_info);
- WPA_PUT_BE16(err->key_length, 0);
- os_memcpy(err->replay_counter, sm->request_counter,
- WPA_REPLAY_COUNTER_LEN);
- inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN);
-
- WPA_PUT_BE16(err->key_data_length, (u16) kde_len);
- pos = (u8 *) (err + 1);
-
- if (peer) {
- /* Peer MAC Address KDE */
- pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN);
- }
-
- /* Error KDE */
- error.mui = host_to_be16(mui);
- error.error_type = host_to_be16(error_type);
- wpa_add_kde(pos, RSN_KEY_DATA_ERROR, (u8 *) &error, sizeof(error));
-
- if (peer) {
- wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK Error (peer "
- MACSTR " mui %d error_type %d)",
- MAC2STR(peer), mui, error_type);
- } else {
- wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK Error "
- "(mui %d error_type %d)", mui, error_type);
- }
-
- wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, dst,
- ETH_P_EAPOL, rbuf, rlen, err192->key_mic);
-
- return 0;
-}
-
-
-static int wpa_supplicant_send_smk_m3(struct wpa_sm *sm,
- const unsigned char *src_addr,
- const struct wpa_eapol_key *key,
- int ver, struct wpa_peerkey *peerkey)
-{
- size_t rlen;
- struct wpa_eapol_key *reply;
- struct wpa_eapol_key_192 *reply192;
- u8 *rbuf, *pos;
- size_t kde_len;
- u16 key_info;
-
- /* KDEs: Peer RSN IE, Initiator MAC Address, Initiator Nonce */
- kde_len = peerkey->rsnie_p_len +
- 2 + RSN_SELECTOR_LEN + ETH_ALEN +
- 2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN;
-
- rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY,
- NULL, sizeof(*reply) + kde_len, &rlen,
- (void *) &reply);
- if (rbuf == NULL)
- return -1;
- reply192 = (struct wpa_eapol_key_192 *) reply;
-
- reply->type = EAPOL_KEY_TYPE_RSN;
- key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC |
- WPA_KEY_INFO_SECURE;
- WPA_PUT_BE16(reply->key_info, key_info);
- WPA_PUT_BE16(reply->key_length, 0);
- os_memcpy(reply->replay_counter, key->replay_counter,
- WPA_REPLAY_COUNTER_LEN);
-
- os_memcpy(reply->key_nonce, peerkey->pnonce, WPA_NONCE_LEN);
-
- WPA_PUT_BE16(reply->key_data_length, (u16) kde_len);
- pos = (u8 *) (reply + 1);
-
- /* Peer RSN IE */
- pos = wpa_add_ie(pos, peerkey->rsnie_p, peerkey->rsnie_p_len);
-
- /* Initiator MAC Address KDE */
- pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peerkey->addr, ETH_ALEN);
-
- /* Initiator Nonce */
- wpa_add_kde(pos, RSN_KEY_DATA_NONCE, peerkey->inonce, WPA_NONCE_LEN);
-
- wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK M3");
- wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, src_addr,
- ETH_P_EAPOL, rbuf, rlen, reply192->key_mic);
-
- return 0;
-}
-
-
-static int wpa_supplicant_process_smk_m2(
- struct wpa_sm *sm, const unsigned char *src_addr,
- const struct wpa_eapol_key *key, size_t extra_len, int ver)
-{
- struct wpa_peerkey *peerkey;
- struct wpa_eapol_ie_parse kde;
- struct wpa_ie_data ie;
- int cipher;
- struct rsn_ie_hdr *hdr;
- u8 *pos;
-
- wpa_printf(MSG_DEBUG, "RSN: Received SMK M2");
-
- if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) {
- wpa_printf(MSG_INFO, "RSN: SMK handshake not allowed for "
- "the current network");
- return -1;
- }
-
- if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) <
- 0) {
- wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M2");
- return -1;
- }
-
- if (kde.rsn_ie == NULL || kde.mac_addr == NULL ||
- kde.mac_addr_len < ETH_ALEN) {
- wpa_printf(MSG_INFO, "RSN: No RSN IE or MAC address KDE in "
- "SMK M2");
- return -1;
- }
-
- wpa_printf(MSG_DEBUG, "RSN: SMK M2 - SMK initiator " MACSTR,
- MAC2STR(kde.mac_addr));
-
- if (kde.rsn_ie_len > PEERKEY_MAX_IE_LEN) {
- wpa_printf(MSG_INFO, "RSN: Too long Initiator RSN IE in SMK "
- "M2");
- return -1;
- }
-
- if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) {
- wpa_printf(MSG_INFO, "RSN: Failed to parse RSN IE in SMK M2");
- return -1;
- }
-
- cipher = wpa_pick_pairwise_cipher(ie.pairwise_cipher &
- sm->allowed_pairwise_cipher, 0);
- if (cipher < 0) {
- wpa_printf(MSG_INFO, "RSN: No acceptable cipher in SMK M2");
- wpa_supplicant_send_smk_error(sm, src_addr, kde.mac_addr,
- STK_MUI_SMK, STK_ERR_CPHR_NS,
- ver);
- return -1;
- }
- wpa_printf(MSG_DEBUG, "RSN: Using %s for PeerKey",
- wpa_cipher_txt(cipher));
-
- /* TODO: find existing entry and if found, use that instead of adding
- * a new one; how to handle the case where both ends initiate at the
- * same time? */
- peerkey = os_zalloc(sizeof(*peerkey));
- if (peerkey == NULL)
- return -1;
- os_memcpy(peerkey->addr, kde.mac_addr, ETH_ALEN);
- os_memcpy(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN);
- os_memcpy(peerkey->rsnie_i, kde.rsn_ie, kde.rsn_ie_len);
- peerkey->rsnie_i_len = kde.rsn_ie_len;
- peerkey->cipher = cipher;
- peerkey->akmp = ie.key_mgmt;
-
- if (random_get_bytes(peerkey->pnonce, WPA_NONCE_LEN)) {
- wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
- "WPA: Failed to get random data for PNonce");
- wpa_supplicant_peerkey_free(sm, peerkey);
- return -1;
- }
-
- hdr = (struct rsn_ie_hdr *) peerkey->rsnie_p;
- hdr->elem_id = WLAN_EID_RSN;
- WPA_PUT_LE16(hdr->version, RSN_VERSION);
- pos = (u8 *) (hdr + 1);
- /* Group Suite can be anything for SMK RSN IE; receiver will just
- * ignore it. */
- RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
- pos += RSN_SELECTOR_LEN;
- /* Include only the selected cipher in pairwise cipher suite */
- WPA_PUT_LE16(pos, 1);
- pos += 2;
- RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN, cipher));
- pos += RSN_SELECTOR_LEN;
-
- hdr->len = (pos - peerkey->rsnie_p) - 2;
- peerkey->rsnie_p_len = pos - peerkey->rsnie_p;
- wpa_hexdump(MSG_DEBUG, "WPA: RSN IE for SMK handshake",
- peerkey->rsnie_p, peerkey->rsnie_p_len);
-
- wpa_supplicant_send_smk_m3(sm, src_addr, key, ver, peerkey);
-
- peerkey->next = sm->peerkey;
- sm->peerkey = peerkey;
-
- return 0;
-}
-
-
-/**
- * rsn_smkid - Derive SMK identifier
- * @smk: Station master key (32 bytes)
- * @pnonce: Peer Nonce
- * @mac_p: Peer MAC address
- * @inonce: Initiator Nonce
- * @mac_i: Initiator MAC address
- * @akmp: Negotiated AKM
- *
- * 8.5.1.4 Station to station (STK) key hierarchy
- * SMKID = HMAC-SHA1-128(SMK, "SMK Name" || PNonce || MAC_P || INonce || MAC_I)
- */
-static void rsn_smkid(const u8 *smk, const u8 *pnonce, const u8 *mac_p,
- const u8 *inonce, const u8 *mac_i, u8 *smkid,
- int akmp)
-{
- char *title = "SMK Name";
- const u8 *addr[5];
- const size_t len[5] = { 8, WPA_NONCE_LEN, ETH_ALEN, WPA_NONCE_LEN,
- ETH_ALEN };
- unsigned char hash[SHA256_MAC_LEN];
-
- addr[0] = (u8 *) title;
- addr[1] = pnonce;
- addr[2] = mac_p;
- addr[3] = inonce;
- addr[4] = mac_i;
-
-#ifdef CONFIG_IEEE80211W
- if (wpa_key_mgmt_sha256(akmp))
- hmac_sha256_vector(smk, PMK_LEN, 5, addr, len, hash);
- else
-#endif /* CONFIG_IEEE80211W */
- hmac_sha1_vector(smk, PMK_LEN, 5, addr, len, hash);
- os_memcpy(smkid, hash, PMKID_LEN);
-}
-
-
-static void wpa_supplicant_send_stk_1_of_4(struct wpa_sm *sm,
- struct wpa_peerkey *peerkey)
-{
- size_t mlen;
- struct wpa_eapol_key *msg;
- u8 *mbuf;
- size_t kde_len;
- u16 key_info, ver;
-
- kde_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN;
-
- mbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
- sizeof(*msg) + kde_len, &mlen,
- (void *) &msg);
- if (mbuf == NULL)
- return;
-
- msg->type = EAPOL_KEY_TYPE_RSN;
-
- if (peerkey->cipher != WPA_CIPHER_TKIP)
- ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
- else
- ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
-
- key_info = ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_ACK;
- WPA_PUT_BE16(msg->key_info, key_info);
-
- if (peerkey->cipher != WPA_CIPHER_TKIP)
- WPA_PUT_BE16(msg->key_length, 16);
- else
- WPA_PUT_BE16(msg->key_length, 32);
-
- os_memcpy(msg->replay_counter, peerkey->replay_counter,
- WPA_REPLAY_COUNTER_LEN);
- inc_byte_array(peerkey->replay_counter, WPA_REPLAY_COUNTER_LEN);
-
- WPA_PUT_BE16(msg->key_data_length, kde_len);
- wpa_add_kde((u8 *) (msg + 1), RSN_KEY_DATA_PMKID,
- peerkey->smkid, PMKID_LEN);
-
- if (random_get_bytes(peerkey->inonce, WPA_NONCE_LEN)) {
- wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
- "RSN: Failed to get random data for INonce (STK)");
- os_free(mbuf);
- return;
- }
- wpa_hexdump(MSG_DEBUG, "RSN: INonce for STK 4-Way Handshake",
- peerkey->inonce, WPA_NONCE_LEN);
- os_memcpy(msg->key_nonce, peerkey->inonce, WPA_NONCE_LEN);
-
- wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 1/4 to " MACSTR,
- MAC2STR(peerkey->addr));
- wpa_eapol_key_send(sm, NULL, 0, ver, peerkey->addr, ETH_P_EAPOL,
- mbuf, mlen, NULL);
-}
-
-
-static void wpa_supplicant_send_stk_3_of_4(struct wpa_sm *sm,
- struct wpa_peerkey *peerkey)
-{
- size_t mlen;
- struct wpa_eapol_key *msg;
- u8 *mbuf, *pos;
- size_t kde_len;
- u16 key_info, ver;
- be32 lifetime;
-
- kde_len = peerkey->rsnie_i_len +
- 2 + RSN_SELECTOR_LEN + sizeof(lifetime);
-
- mbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
- sizeof(*msg) + kde_len, &mlen,
- (void *) &msg);
- if (mbuf == NULL)
- return;
-
- msg->type = EAPOL_KEY_TYPE_RSN;
-
- if (peerkey->cipher != WPA_CIPHER_TKIP)
- ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
- else
- ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
-
- key_info = ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_ACK |
- WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE;
- WPA_PUT_BE16(msg->key_info, key_info);
-
- if (peerkey->cipher != WPA_CIPHER_TKIP)
- WPA_PUT_BE16(msg->key_length, 16);
- else
- WPA_PUT_BE16(msg->key_length, 32);
-
- os_memcpy(msg->replay_counter, peerkey->replay_counter,
- WPA_REPLAY_COUNTER_LEN);
- inc_byte_array(peerkey->replay_counter, WPA_REPLAY_COUNTER_LEN);
-
- WPA_PUT_BE16(msg->key_data_length, kde_len);
- pos = (u8 *) (msg + 1);
- pos = wpa_add_ie(pos, peerkey->rsnie_i, peerkey->rsnie_i_len);
- lifetime = host_to_be32(peerkey->lifetime);
- wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME,
- (u8 *) &lifetime, sizeof(lifetime));
-
- os_memcpy(msg->key_nonce, peerkey->inonce, WPA_NONCE_LEN);
-
- wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 3/4 to " MACSTR,
- MAC2STR(peerkey->addr));
- wpa_eapol_key_send(sm, peerkey->stk.kck, peerkey->stk.kck_len, ver,
- peerkey->addr, ETH_P_EAPOL, mbuf, mlen,
- msg->key_mic);
-}
-
-
-static int wpa_supplicant_process_smk_m4(struct wpa_peerkey *peerkey,
- struct wpa_eapol_ie_parse *kde)
-{
- wpa_printf(MSG_DEBUG, "RSN: Received SMK M4 (Initiator " MACSTR ")",
- MAC2STR(kde->mac_addr));
-
- if (os_memcmp(kde->smk + PMK_LEN, peerkey->pnonce, WPA_NONCE_LEN) != 0)
- {
- wpa_printf(MSG_INFO, "RSN: PNonce in SMK KDE does not "
- "match with the one used in SMK M3");
- return -1;
- }
-
- if (os_memcmp(kde->nonce, peerkey->inonce, WPA_NONCE_LEN) != 0) {
- wpa_printf(MSG_INFO, "RSN: INonce in SMK M4 did not "
- "match with the one received in SMK M2");
- return -1;
- }
-
- return 0;
-}
-
-
-static int wpa_supplicant_process_smk_m5(struct wpa_sm *sm,
- const unsigned char *src_addr,
- const struct wpa_eapol_key *key,
- int ver,
- struct wpa_peerkey *peerkey,
- struct wpa_eapol_ie_parse *kde)
-{
- int cipher;
- struct wpa_ie_data ie;
-
- wpa_printf(MSG_DEBUG, "RSN: Received SMK M5 (Peer " MACSTR ")",
- MAC2STR(kde->mac_addr));
- if (kde->rsn_ie == NULL || kde->rsn_ie_len > PEERKEY_MAX_IE_LEN ||
- wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0) {
- wpa_printf(MSG_INFO, "RSN: No RSN IE in SMK M5");
- /* TODO: abort negotiation */
- return -1;
- }
-
- if (os_memcmp(key->key_nonce, peerkey->inonce, WPA_NONCE_LEN) != 0) {
- wpa_printf(MSG_INFO, "RSN: Key Nonce in SMK M5 does "
- "not match with INonce used in SMK M1");
- return -1;
- }
-
- if (os_memcmp(kde->smk + PMK_LEN, peerkey->inonce, WPA_NONCE_LEN) != 0)
- {
- wpa_printf(MSG_INFO, "RSN: INonce in SMK KDE does not "
- "match with the one used in SMK M1");
- return -1;
- }
-
- os_memcpy(peerkey->rsnie_p, kde->rsn_ie, kde->rsn_ie_len);
- peerkey->rsnie_p_len = kde->rsn_ie_len;
- os_memcpy(peerkey->pnonce, kde->nonce, WPA_NONCE_LEN);
-
- cipher = wpa_pick_pairwise_cipher(ie.pairwise_cipher &
- sm->allowed_pairwise_cipher, 0);
- if (cipher < 0) {
- wpa_printf(MSG_INFO, "RSN: SMK Peer STA " MACSTR " selected "
- "unacceptable cipher", MAC2STR(kde->mac_addr));
- wpa_supplicant_send_smk_error(sm, src_addr, kde->mac_addr,
- STK_MUI_SMK, STK_ERR_CPHR_NS,
- ver);
- /* TODO: abort negotiation */
- return -1;
- }
- wpa_printf(MSG_DEBUG, "RSN: Using %s for PeerKey",
- wpa_cipher_txt(cipher));
- peerkey->cipher = cipher;
-
- return 0;
-}
-
-
-static int wpa_supplicant_process_smk_m45(
- struct wpa_sm *sm, const unsigned char *src_addr,
- const struct wpa_eapol_key *key, size_t extra_len, int ver)
-{
- struct wpa_peerkey *peerkey;
- struct wpa_eapol_ie_parse kde;
- u32 lifetime;
-
- if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) {
- wpa_printf(MSG_DEBUG, "RSN: SMK handshake not allowed for "
- "the current network");
- return -1;
- }
-
- if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) <
- 0) {
- wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M4/M5");
- return -1;
- }
-
- if (kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN ||
- kde.nonce == NULL || kde.nonce_len < WPA_NONCE_LEN ||
- kde.smk == NULL || kde.smk_len < PMK_LEN + WPA_NONCE_LEN ||
- kde.lifetime == NULL || kde.lifetime_len < 4) {
- wpa_printf(MSG_INFO, "RSN: No MAC Address, Nonce, SMK, or "
- "Lifetime KDE in SMK M4/M5");
- return -1;
- }
-
- for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) {
- if (os_memcmp(peerkey->addr, kde.mac_addr, ETH_ALEN) == 0 &&
- os_memcmp(peerkey->initiator ? peerkey->inonce :
- peerkey->pnonce,
- key->key_nonce, WPA_NONCE_LEN) == 0)
- break;
- }
- if (peerkey == NULL) {
- wpa_printf(MSG_INFO, "RSN: No matching SMK handshake found "
- "for SMK M4/M5: peer " MACSTR,
- MAC2STR(kde.mac_addr));
- return -1;
- }
-
- if (peerkey->initiator) {
- if (wpa_supplicant_process_smk_m5(sm, src_addr, key, ver,
- peerkey, &kde) < 0)
- return -1;
- } else {
- if (wpa_supplicant_process_smk_m4(peerkey, &kde) < 0)
- return -1;
- }
-
- os_memcpy(peerkey->smk, kde.smk, PMK_LEN);
- peerkey->smk_complete = 1;
- wpa_hexdump_key(MSG_DEBUG, "RSN: SMK", peerkey->smk, PMK_LEN);
- lifetime = WPA_GET_BE32(kde.lifetime);
- wpa_printf(MSG_DEBUG, "RSN: SMK lifetime %u seconds", lifetime);
- if (lifetime > 1000000000)
- lifetime = 1000000000; /* avoid overflowing eloop time */
- peerkey->lifetime = lifetime;
- eloop_register_timeout(lifetime, 0, wpa_supplicant_smk_timeout,
- sm, peerkey);
-
- if (peerkey->initiator) {
- rsn_smkid(peerkey->smk, peerkey->pnonce, peerkey->addr,
- peerkey->inonce, sm->own_addr, peerkey->smkid,
- peerkey->akmp);
- wpa_supplicant_send_stk_1_of_4(sm, peerkey);
- } else {
- rsn_smkid(peerkey->smk, peerkey->pnonce, sm->own_addr,
- peerkey->inonce, peerkey->addr, peerkey->smkid,
- peerkey->akmp);
- }
- wpa_hexdump(MSG_DEBUG, "RSN: SMKID", peerkey->smkid, PMKID_LEN);
-
- return 0;
-}
-
-
-static int wpa_supplicant_process_smk_error(
- struct wpa_sm *sm, const unsigned char *src_addr,
- const struct wpa_eapol_key *key, size_t extra_len)
-{
- struct wpa_eapol_ie_parse kde;
- struct rsn_error_kde error;
- u8 peer[ETH_ALEN];
- u16 error_type;
-
- wpa_printf(MSG_DEBUG, "RSN: Received SMK Error");
-
- if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) {
- wpa_printf(MSG_DEBUG, "RSN: SMK handshake not allowed for "
- "the current network");
- return -1;
- }
-
- if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) <
- 0) {
- wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK Error");
- return -1;
- }
-
- if (kde.error == NULL || kde.error_len < sizeof(error)) {
- wpa_printf(MSG_INFO, "RSN: No Error KDE in SMK Error");
- return -1;
- }
-
- if (kde.mac_addr && kde.mac_addr_len >= ETH_ALEN)
- os_memcpy(peer, kde.mac_addr, ETH_ALEN);
- else
- os_memset(peer, 0, ETH_ALEN);
- os_memcpy(&error, kde.error, sizeof(error));
- error_type = be_to_host16(error.error_type);
- wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
- "RSN: SMK Error KDE received: MUI %d error_type %d peer "
- MACSTR,
- be_to_host16(error.mui), error_type,
- MAC2STR(peer));
-
- if (kde.mac_addr &&
- (error_type == STK_ERR_STA_NR || error_type == STK_ERR_STA_NRSN ||
- error_type == STK_ERR_CPHR_NS)) {
- struct wpa_peerkey *peerkey;
-
- for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) {
- if (os_memcmp(peerkey->addr, kde.mac_addr, ETH_ALEN) ==
- 0)
- break;
- }
- if (peerkey == NULL) {
- wpa_printf(MSG_DEBUG, "RSN: No matching SMK handshake "
- "found for SMK Error");
- return -1;
- }
- /* TODO: abort SMK/STK handshake and remove all related keys */
- }
-
- return 0;
-}
-
-
-static void wpa_supplicant_process_stk_1_of_4(struct wpa_sm *sm,
- struct wpa_peerkey *peerkey,
- const struct wpa_eapol_key *key,
- u16 ver, const u8 *key_data,
- size_t key_data_len)
-{
- struct wpa_eapol_ie_parse ie;
- size_t kde_buf_len;
- struct wpa_ptk *stk;
- u8 buf[8], *kde_buf, *pos;
- be32 lifetime;
-
- wpa_printf(MSG_DEBUG, "RSN: RX message 1 of STK 4-Way Handshake from "
- MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver);
-
- os_memset(&ie, 0, sizeof(ie));
-
- /* RSN: msg 1/4 should contain SMKID for the selected SMK */
- wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", key_data, key_data_len);
- if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0 ||
- ie.pmkid == NULL) {
- wpa_printf(MSG_DEBUG, "RSN: No SMKID in STK 1/4");
- return;
- }
- if (os_memcmp_const(ie.pmkid, peerkey->smkid, PMKID_LEN) != 0) {
- wpa_hexdump(MSG_DEBUG, "RSN: Unknown SMKID in STK 1/4",
- ie.pmkid, PMKID_LEN);
- return;
- }
-
- if (random_get_bytes(peerkey->pnonce, WPA_NONCE_LEN)) {
- wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
- "RSN: Failed to get random data for PNonce");
- return;
- }
- wpa_hexdump(MSG_DEBUG, "WPA: Renewed PNonce",
- peerkey->pnonce, WPA_NONCE_LEN);
-
- /* Calculate STK which will be stored as a temporary STK until it has
- * been verified when processing message 3/4. */
- stk = &peerkey->tstk;
- wpa_pmk_to_ptk(peerkey->smk, PMK_LEN, "Peer key expansion",
- sm->own_addr, peerkey->addr,
- peerkey->pnonce, key->key_nonce,
- stk, peerkey->akmp, peerkey->cipher);
- /* Supplicant: swap tx/rx Mic keys */
- os_memcpy(buf, &stk->tk[16], 8);
- os_memcpy(&stk->tk[16], &stk->tk[24], 8);
- os_memcpy(&stk->tk[24], buf, 8);
- peerkey->tstk_set = 1;
-
- kde_buf_len = peerkey->rsnie_p_len +
- 2 + RSN_SELECTOR_LEN + sizeof(lifetime) +
- 2 + RSN_SELECTOR_LEN + PMKID_LEN;
- kde_buf = os_malloc(kde_buf_len);
- if (kde_buf == NULL)
- return;
- pos = kde_buf;
- pos = wpa_add_ie(pos, peerkey->rsnie_p, peerkey->rsnie_p_len);
- lifetime = host_to_be32(peerkey->lifetime);
- pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME,
- (u8 *) &lifetime, sizeof(lifetime));
- wpa_add_kde(pos, RSN_KEY_DATA_PMKID, peerkey->smkid, PMKID_LEN);
-
- if (wpa_supplicant_send_2_of_4(sm, peerkey->addr, key, ver,
- peerkey->pnonce, kde_buf, kde_buf_len,
- stk)) {
- os_free(kde_buf);
- return;
- }
- os_free(kde_buf);
-
- os_memcpy(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN);
-}
-
-
-static void wpa_supplicant_update_smk_lifetime(struct wpa_sm *sm,
- struct wpa_peerkey *peerkey,
- struct wpa_eapol_ie_parse *kde)
-{
- u32 lifetime;
-
- if (kde->lifetime == NULL || kde->lifetime_len < sizeof(lifetime))
- return;
-
- lifetime = WPA_GET_BE32(kde->lifetime);
-
- if (lifetime >= peerkey->lifetime) {
- wpa_printf(MSG_DEBUG, "RSN: Peer used SMK lifetime %u seconds "
- "which is larger than or equal to own value %u "
- "seconds - ignored", lifetime, peerkey->lifetime);
- return;
- }
-
- wpa_printf(MSG_DEBUG, "RSN: Peer used shorter SMK lifetime %u seconds "
- "(own was %u seconds) - updated",
- lifetime, peerkey->lifetime);
- peerkey->lifetime = lifetime;
-
- eloop_cancel_timeout(wpa_supplicant_smk_timeout, sm, peerkey);
- eloop_register_timeout(lifetime, 0, wpa_supplicant_smk_timeout,
- sm, peerkey);
-}
-
-
-static void wpa_supplicant_process_stk_2_of_4(struct wpa_sm *sm,
- struct wpa_peerkey *peerkey,
- const struct wpa_eapol_key *key,
- u16 ver, const u8 *key_data,
- size_t key_data_len)
-{
- struct wpa_eapol_ie_parse kde;
-
- wpa_printf(MSG_DEBUG, "RSN: RX message 2 of STK 4-Way Handshake from "
- MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver);
-
- os_memset(&kde, 0, sizeof(kde));
-
- /* RSN: msg 2/4 should contain SMKID for the selected SMK and RSN IE
- * from the peer. It may also include Lifetime KDE. */
- wpa_hexdump(MSG_DEBUG, "RSN: msg 2/4 key data", key_data, key_data_len);
- if (wpa_supplicant_parse_ies(key_data, key_data_len, &kde) < 0 ||
- kde.pmkid == NULL || kde.rsn_ie == NULL) {
- wpa_printf(MSG_DEBUG, "RSN: No SMKID or RSN IE in STK 2/4");
- return;
- }
-
- if (os_memcmp_const(kde.pmkid, peerkey->smkid, PMKID_LEN) != 0) {
- wpa_hexdump(MSG_DEBUG, "RSN: Unknown SMKID in STK 2/4",
- kde.pmkid, PMKID_LEN);
- return;
- }
-
- if (kde.rsn_ie_len != peerkey->rsnie_p_len ||
- os_memcmp(kde.rsn_ie, peerkey->rsnie_p, kde.rsn_ie_len) != 0) {
- wpa_printf(MSG_INFO, "RSN: Peer RSN IE in SMK and STK "
- "handshakes did not match");
- wpa_hexdump(MSG_DEBUG, "RSN: Peer RSN IE in SMK handshake",
- peerkey->rsnie_p, peerkey->rsnie_p_len);
- wpa_hexdump(MSG_DEBUG, "RSN: Peer RSN IE in STK handshake",
- kde.rsn_ie, kde.rsn_ie_len);
- return;
- }
-
- wpa_supplicant_update_smk_lifetime(sm, peerkey, &kde);
-
- wpa_supplicant_send_stk_3_of_4(sm, peerkey);
- os_memcpy(peerkey->pnonce, key->key_nonce, WPA_NONCE_LEN);
-}
-
-
-static void wpa_supplicant_process_stk_3_of_4(struct wpa_sm *sm,
- struct wpa_peerkey *peerkey,
- const struct wpa_eapol_key *key,
- u16 ver, const u8 *key_data,
- size_t key_data_len)
-{
- struct wpa_eapol_ie_parse kde;
- size_t key_len;
- const u8 *_key;
- u8 key_buf[32], rsc[6];
-
- wpa_printf(MSG_DEBUG, "RSN: RX message 3 of STK 4-Way Handshake from "
- MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver);
-
- os_memset(&kde, 0, sizeof(kde));
-
- /* RSN: msg 3/4 should contain Initiator RSN IE. It may also include
- * Lifetime KDE. */
- wpa_hexdump(MSG_DEBUG, "RSN: msg 3/4 key data", key_data, key_data_len);
- if (wpa_supplicant_parse_ies(key_data, key_data_len, &kde) < 0) {
- wpa_printf(MSG_DEBUG, "RSN: Failed to parse key data in "
- "STK 3/4");
- return;
- }
-
- if (kde.rsn_ie_len != peerkey->rsnie_i_len ||
- os_memcmp(kde.rsn_ie, peerkey->rsnie_i, kde.rsn_ie_len) != 0) {
- wpa_printf(MSG_INFO, "RSN: Initiator RSN IE in SMK and STK "
- "handshakes did not match");
- wpa_hexdump(MSG_DEBUG, "RSN: Initiator RSN IE in SMK "
- "handshake",
- peerkey->rsnie_i, peerkey->rsnie_i_len);
- wpa_hexdump(MSG_DEBUG, "RSN: Initiator RSN IE in STK "
- "handshake",
- kde.rsn_ie, kde.rsn_ie_len);
- return;
- }
-
- if (os_memcmp(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN) != 0) {
- wpa_printf(MSG_WARNING, "RSN: INonce from message 1 of STK "
- "4-Way Handshake differs from 3 of STK 4-Way "
- "Handshake - drop packet (src=" MACSTR ")",
- MAC2STR(peerkey->addr));
- return;
- }
-
- wpa_supplicant_update_smk_lifetime(sm, peerkey, &kde);
-
- if (wpa_supplicant_send_4_of_4(sm, peerkey->addr, key, ver,
- WPA_GET_BE16(key->key_info),
- &peerkey->stk))
- return;
-
- _key = peerkey->stk.tk;
- if (peerkey->cipher == WPA_CIPHER_TKIP) {
- /* Swap Tx/Rx keys for Michael MIC */
- os_memcpy(key_buf, _key, 16);
- os_memcpy(key_buf + 16, _key + 24, 8);
- os_memcpy(key_buf + 24, _key + 16, 8);
- _key = key_buf;
- key_len = 32;
- } else
- key_len = 16;
-
- os_memset(rsc, 0, 6);
- if (wpa_sm_set_key(sm, peerkey->cipher, peerkey->addr, 0, 1,
- rsc, sizeof(rsc), _key, key_len) < 0) {
- os_memset(key_buf, 0, sizeof(key_buf));
- wpa_printf(MSG_WARNING, "RSN: Failed to set STK to the "
- "driver.");
- return;
- }
- os_memset(key_buf, 0, sizeof(key_buf));
-}
-
-
-static void wpa_supplicant_process_stk_4_of_4(struct wpa_sm *sm,
- struct wpa_peerkey *peerkey,
- const struct wpa_eapol_key *key,
- u16 ver)
-{
- u8 rsc[6];
-
- wpa_printf(MSG_DEBUG, "RSN: RX message 4 of STK 4-Way Handshake from "
- MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver);
-
- os_memset(rsc, 0, 6);
- if (wpa_sm_set_key(sm, peerkey->cipher, peerkey->addr, 0, 1,
- rsc, sizeof(rsc), peerkey->stk.tk,
- peerkey->cipher == WPA_CIPHER_TKIP ? 32 : 16) < 0) {
- wpa_printf(MSG_WARNING, "RSN: Failed to set STK to the "
- "driver.");
- return;
- }
-}
-
-
-/**
- * peerkey_verify_eapol_key_mic - Verify PeerKey MIC
- * @sm: Pointer to WPA state machine data from wpa_sm_init()
- * @peerkey: Pointer to the PeerKey data for the peer
- * @key: Pointer to the EAPOL-Key frame header
- * @ver: Version bits from EAPOL-Key Key Info
- * @buf: Pointer to the beginning of EAPOL-Key frame
- * @len: Length of the EAPOL-Key frame
- * Returns: 0 on success, -1 on failure
- */
-int peerkey_verify_eapol_key_mic(struct wpa_sm *sm,
- struct wpa_peerkey *peerkey,
- struct wpa_eapol_key_192 *key, u16 ver,
- const u8 *buf, size_t len)
-{
- u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN];
- size_t mic_len = 16;
- int ok = 0;
-
- if (peerkey->initiator && !peerkey->stk_set) {
- wpa_pmk_to_ptk(peerkey->smk, PMK_LEN, "Peer key expansion",
- sm->own_addr, peerkey->addr,
- peerkey->inonce, key->key_nonce,
- &peerkey->stk, peerkey->akmp, peerkey->cipher);
- peerkey->stk_set = 1;
- }
-
- os_memcpy(mic, key->key_mic, mic_len);
- if (peerkey->tstk_set) {
- os_memset(key->key_mic, 0, mic_len);
- wpa_eapol_key_mic(peerkey->tstk.kck, peerkey->tstk.kck_len,
- sm->key_mgmt, ver, buf, len, key->key_mic);
- if (os_memcmp_const(mic, key->key_mic, mic_len) != 0) {
- wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC "
- "when using TSTK - ignoring TSTK");
- } else {
- ok = 1;
- peerkey->tstk_set = 0;
- peerkey->stk_set = 1;
- os_memcpy(&peerkey->stk, &peerkey->tstk,
- sizeof(peerkey->stk));
- os_memset(&peerkey->tstk, 0, sizeof(peerkey->tstk));
- }
- }
-
- if (!ok && peerkey->stk_set) {
- os_memset(key->key_mic, 0, mic_len);
- wpa_eapol_key_mic(peerkey->stk.kck, peerkey->stk.kck_len,
- sm->key_mgmt, ver, buf, len, key->key_mic);
- if (os_memcmp_const(mic, key->key_mic, mic_len) != 0) {
- wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC "
- "- dropping packet");
- return -1;
- }
- ok = 1;
- }
-
- if (!ok) {
- wpa_printf(MSG_WARNING, "RSN: Could not verify EAPOL-Key MIC "
- "- dropping packet");
- return -1;
- }
-
- os_memcpy(peerkey->replay_counter, key->replay_counter,
- WPA_REPLAY_COUNTER_LEN);
- peerkey->replay_counter_set = 1;
- return 0;
-}
-
-
-/**
- * wpa_sm_stkstart - Send EAPOL-Key Request for STK handshake (STK M1)
- * @sm: Pointer to WPA state machine data from wpa_sm_init()
- * @peer: MAC address of the peer STA
- * Returns: 0 on success, or -1 on failure
- *
- * Send an EAPOL-Key Request to the current authenticator to start STK
- * handshake with the peer.
- */
-int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer)
-{
- size_t rlen, kde_len;
- struct wpa_eapol_key *req;
- int key_info, ver;
- u8 bssid[ETH_ALEN], *rbuf, *pos, *count_pos;
- u16 count;
- struct rsn_ie_hdr *hdr;
- struct wpa_peerkey *peerkey;
- struct wpa_ie_data ie;
-
- if (sm->proto != WPA_PROTO_RSN || !sm->ptk_set || !sm->peerkey_enabled)
- return -1;
-
- if (sm->ap_rsn_ie &&
- wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &ie) == 0 &&
- !(ie.capabilities & WPA_CAPABILITY_PEERKEY_ENABLED)) {
- wpa_printf(MSG_DEBUG, "RSN: Current AP does not support STK");
- return -1;
- }
-
- if (sm->pairwise_cipher != WPA_CIPHER_TKIP)
- ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
- else
- ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
-
- if (wpa_sm_get_bssid(sm, bssid) < 0) {
- wpa_printf(MSG_WARNING, "Failed to read BSSID for EAPOL-Key "
- "SMK M1");
- return -1;
- }
-
- /* TODO: find existing entry and if found, use that instead of adding
- * a new one */
- peerkey = os_zalloc(sizeof(*peerkey));
- if (peerkey == NULL)
- return -1;
- peerkey->initiator = 1;
- os_memcpy(peerkey->addr, peer, ETH_ALEN);
- peerkey->akmp = sm->key_mgmt;
-
- /* SMK M1:
- * EAPOL-Key(S=1, M=1, A=0, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce,
- * MIC=MIC, DataKDs=(RSNIE_I, MAC_P KDE))
- */
-
- hdr = (struct rsn_ie_hdr *) peerkey->rsnie_i;
- hdr->elem_id = WLAN_EID_RSN;
- WPA_PUT_LE16(hdr->version, RSN_VERSION);
- pos = (u8 *) (hdr + 1);
- /* Group Suite can be anything for SMK RSN IE; receiver will just
- * ignore it. */
- RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
- pos += RSN_SELECTOR_LEN;
- count_pos = pos;
- pos += 2;
-
- count = rsn_cipher_put_suites(pos, sm->allowed_pairwise_cipher);
- pos += count * RSN_SELECTOR_LEN;
- WPA_PUT_LE16(count_pos, count);
-
- hdr->len = (pos - peerkey->rsnie_i) - 2;
- peerkey->rsnie_i_len = pos - peerkey->rsnie_i;
- wpa_hexdump(MSG_DEBUG, "WPA: RSN IE for SMK handshake",
- peerkey->rsnie_i, peerkey->rsnie_i_len);
-
- kde_len = peerkey->rsnie_i_len + 2 + RSN_SELECTOR_LEN + ETH_ALEN;
-
- rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
- sizeof(*req) + kde_len, &rlen,
- (void *) &req);
- if (rbuf == NULL) {
- wpa_supplicant_peerkey_free(sm, peerkey);
- return -1;
- }
-
- req->type = EAPOL_KEY_TYPE_RSN;
- key_info = WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC |
- WPA_KEY_INFO_SECURE | WPA_KEY_INFO_REQUEST | ver;
- WPA_PUT_BE16(req->key_info, key_info);
- WPA_PUT_BE16(req->key_length, 0);
- os_memcpy(req->replay_counter, sm->request_counter,
- WPA_REPLAY_COUNTER_LEN);
- inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN);
-
- if (random_get_bytes(peerkey->inonce, WPA_NONCE_LEN)) {
- wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
- "WPA: Failed to get random data for INonce");
- os_free(rbuf);
- wpa_supplicant_peerkey_free(sm, peerkey);
- return -1;
- }
- os_memcpy(req->key_nonce, peerkey->inonce, WPA_NONCE_LEN);
- wpa_hexdump(MSG_DEBUG, "WPA: INonce for SMK handshake",
- req->key_nonce, WPA_NONCE_LEN);
-
- WPA_PUT_BE16(req->key_data_length, (u16) kde_len);
- pos = (u8 *) (req + 1);
-
- /* Initiator RSN IE */
- pos = wpa_add_ie(pos, peerkey->rsnie_i, peerkey->rsnie_i_len);
- /* Peer MAC address KDE */
- wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN);
-
- wpa_printf(MSG_INFO, "RSN: Sending EAPOL-Key SMK M1 Request (peer "
- MACSTR ")", MAC2STR(peer));
- wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, bssid,
- ETH_P_EAPOL, rbuf, rlen, req->key_mic);
-
- peerkey->next = sm->peerkey;
- sm->peerkey = peerkey;
-
- return 0;
-}
-
-
-/**
- * peerkey_deinit - Free PeerKey values
- * @sm: Pointer to WPA state machine data from wpa_sm_init()
- */
-void peerkey_deinit(struct wpa_sm *sm)
-{
- struct wpa_peerkey *prev, *peerkey = sm->peerkey;
- while (peerkey) {
- prev = peerkey;
- peerkey = peerkey->next;
- wpa_supplicant_peerkey_free(sm, prev);
- }
- sm->peerkey = NULL;
-}
-
-
-void peerkey_rx_eapol_4way(struct wpa_sm *sm, struct wpa_peerkey *peerkey,
- struct wpa_eapol_key *key, u16 key_info, u16 ver,
- const u8 *key_data, size_t key_data_len)
-{
- if ((key_info & (WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK)) ==
- (WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK)) {
- /* 3/4 STK 4-Way Handshake */
- wpa_supplicant_process_stk_3_of_4(sm, peerkey, key, ver,
- key_data, key_data_len);
- } else if (key_info & WPA_KEY_INFO_ACK) {
- /* 1/4 STK 4-Way Handshake */
- wpa_supplicant_process_stk_1_of_4(sm, peerkey, key, ver,
- key_data, key_data_len);
- } else if (key_info & WPA_KEY_INFO_SECURE) {
- /* 4/4 STK 4-Way Handshake */
- wpa_supplicant_process_stk_4_of_4(sm, peerkey, key, ver);
- } else {
- /* 2/4 STK 4-Way Handshake */
- wpa_supplicant_process_stk_2_of_4(sm, peerkey, key, ver,
- key_data, key_data_len);
- }
-}
-
-
-void peerkey_rx_eapol_smk(struct wpa_sm *sm, const u8 *src_addr,
- struct wpa_eapol_key *key, size_t extra_len,
- u16 key_info, u16 ver)
-{
- if (key_info & WPA_KEY_INFO_ERROR) {
- /* SMK Error */
- wpa_supplicant_process_smk_error(sm, src_addr, key, extra_len);
- } else if (key_info & WPA_KEY_INFO_ACK) {
- /* SMK M2 */
- wpa_supplicant_process_smk_m2(sm, src_addr, key, extra_len,
- ver);
- } else {
- /* SMK M4 or M5 */
- wpa_supplicant_process_smk_m45(sm, src_addr, key, extra_len,
- ver);
- }
-}
-
-#endif /* CONFIG_PEERKEY */
diff --git a/freebsd/contrib/wpa/src/rsn_supp/peerkey.h b/freebsd/contrib/wpa/src/rsn_supp/peerkey.h
deleted file mode 100644
index 6ccd948b..00000000
--- a/freebsd/contrib/wpa/src/rsn_supp/peerkey.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * WPA Supplicant - PeerKey for Direct Link Setup (DLS)
- * Copyright (c) 2006-2015, Jouni Malinen <j@w1.fi>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#ifndef PEERKEY_H
-#define PEERKEY_H
-
-#define PEERKEY_MAX_IE_LEN 80
-struct wpa_peerkey {
- struct wpa_peerkey *next;
- int initiator; /* whether this end was initator for SMK handshake */
- u8 addr[ETH_ALEN]; /* other end MAC address */
- u8 inonce[WPA_NONCE_LEN]; /* Initiator Nonce */
- u8 pnonce[WPA_NONCE_LEN]; /* Peer Nonce */
- u8 rsnie_i[PEERKEY_MAX_IE_LEN]; /* Initiator RSN IE */
- size_t rsnie_i_len;
- u8 rsnie_p[PEERKEY_MAX_IE_LEN]; /* Peer RSN IE */
- size_t rsnie_p_len;
- u8 smk[PMK_LEN];
- int smk_complete;
- u8 smkid[PMKID_LEN];
- u32 lifetime;
- int cipher; /* Selected cipher (WPA_CIPHER_*) */
- u8 replay_counter[WPA_REPLAY_COUNTER_LEN];
- int replay_counter_set;
- int akmp;
-
- struct wpa_ptk stk, tstk;
- int stk_set, tstk_set;
-};
-
-
-#ifdef CONFIG_PEERKEY
-
-int peerkey_verify_eapol_key_mic(struct wpa_sm *sm,
- struct wpa_peerkey *peerkey,
- struct wpa_eapol_key_192 *key, u16 ver,
- const u8 *buf, size_t len);
-void peerkey_rx_eapol_4way(struct wpa_sm *sm, struct wpa_peerkey *peerkey,
- struct wpa_eapol_key *key, u16 key_info, u16 ver,
- const u8 *key_data, size_t key_data_len);
-void peerkey_rx_eapol_smk(struct wpa_sm *sm, const u8 *src_addr,
- struct wpa_eapol_key *key, size_t extra_len,
- u16 key_info, u16 ver);
-void peerkey_deinit(struct wpa_sm *sm);
-
-#else /* CONFIG_PEERKEY */
-
-static inline int
-peerkey_verify_eapol_key_mic(struct wpa_sm *sm,
- struct wpa_peerkey *peerkey,
- struct wpa_eapol_key *key, u16 ver,
- const u8 *buf, size_t len)
-{
- return -1;
-}
-
-static inline void
-peerkey_rx_eapol_4way(struct wpa_sm *sm, struct wpa_peerkey *peerkey,
- struct wpa_eapol_key *key, u16 key_info, u16 ver,
- const u8 *key_data, size_t key_data_len)
-{
-}
-
-static inline void
-peerkey_rx_eapol_smk(struct wpa_sm *sm, const u8 *src_addr,
- struct wpa_eapol_key *key, size_t extra_len,
- u16 key_info, u16 ver)
-{
-}
-
-static inline void peerkey_deinit(struct wpa_sm *sm)
-{
-}
-
-#endif /* CONFIG_PEERKEY */
-
-#endif /* PEERKEY_H */
diff --git a/freebsd/contrib/wpa/src/rsn_supp/pmksa_cache.c b/freebsd/contrib/wpa/src/rsn_supp/pmksa_cache.c
index 7f7cbbec..dbf9aba6 100644
--- a/freebsd/contrib/wpa/src/rsn_supp/pmksa_cache.c
+++ b/freebsd/contrib/wpa/src/rsn_supp/pmksa_cache.c
@@ -45,7 +45,10 @@ static void pmksa_cache_free_entry(struct rsn_pmksa_cache *pmksa,
struct rsn_pmksa_cache_entry *entry,
enum pmksa_free_reason reason)
{
- wpa_sm_remove_pmkid(pmksa->sm, entry->aa, entry->pmkid);
+ wpa_sm_remove_pmkid(pmksa->sm, entry->network_ctx, entry->aa,
+ entry->pmkid,
+ entry->fils_cache_id_set ? entry->fils_cache_id :
+ NULL);
pmksa->pmksa_count--;
pmksa->free_cb(entry, pmksa->ctx, reason);
_pmksa_cache_free_entry(entry);
@@ -95,7 +98,7 @@ static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa)
eloop_register_timeout(sec + 1, 0, pmksa_cache_expire, pmksa, NULL);
entry = pmksa->sm->cur_pmksa ? pmksa->sm->cur_pmksa :
- pmksa_cache_get(pmksa, pmksa->sm->bssid, NULL, NULL);
+ pmksa_cache_get(pmksa, pmksa->sm->bssid, NULL, NULL, 0);
if (entry) {
sec = pmksa->pmksa->reauth_time - now.sec;
if (sec < 0)
@@ -118,6 +121,7 @@ static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa)
* @spa: Supplicant address
* @network_ctx: Network configuration context for this PMK
* @akmp: WPA_KEY_MGMT_* used in key derivation
+ * @cache_id: Pointer to FILS Cache Identifier or %NULL if not advertised
* Returns: Pointer to the added PMKSA cache entry or %NULL on error
*
* This function create a PMKSA entry for a new PMK and adds it to the PMKSA
@@ -128,9 +132,10 @@ static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa)
struct rsn_pmksa_cache_entry *
pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
const u8 *pmkid, const u8 *kck, size_t kck_len,
- const u8 *aa, const u8 *spa, void *network_ctx, int akmp)
+ const u8 *aa, const u8 *spa, void *network_ctx, int akmp,
+ const u8 *cache_id)
{
- struct rsn_pmksa_cache_entry *entry, *pos, *prev;
+ struct rsn_pmksa_cache_entry *entry;
struct os_reltime now;
if (pmk_len > PMK_LEN_MAX)
@@ -151,24 +156,38 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
else if (wpa_key_mgmt_suite_b(akmp))
rsn_pmkid_suite_b(kck, kck_len, aa, spa, entry->pmkid);
else
- rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid,
- wpa_key_mgmt_sha256(akmp));
+ rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid, akmp);
os_get_reltime(&now);
entry->expiration = now.sec + pmksa->sm->dot11RSNAConfigPMKLifetime;
entry->reauth_time = now.sec + pmksa->sm->dot11RSNAConfigPMKLifetime *
pmksa->sm->dot11RSNAConfigPMKReauthThreshold / 100;
entry->akmp = akmp;
+ if (cache_id) {
+ entry->fils_cache_id_set = 1;
+ os_memcpy(entry->fils_cache_id, cache_id, FILS_CACHE_ID_LEN);
+ }
os_memcpy(entry->aa, aa, ETH_ALEN);
entry->network_ctx = network_ctx;
+ return pmksa_cache_add_entry(pmksa, entry);
+}
+
+
+struct rsn_pmksa_cache_entry *
+pmksa_cache_add_entry(struct rsn_pmksa_cache *pmksa,
+ struct rsn_pmksa_cache_entry *entry)
+{
+ struct rsn_pmksa_cache_entry *pos, *prev;
+
/* Replace an old entry for the same Authenticator (if found) with the
* new entry */
pos = pmksa->pmksa;
prev = NULL;
while (pos) {
- if (os_memcmp(aa, pos->aa, ETH_ALEN) == 0) {
- if (pos->pmk_len == pmk_len &&
- os_memcmp_const(pos->pmk, pmk, pmk_len) == 0 &&
+ if (os_memcmp(entry->aa, pos->aa, ETH_ALEN) == 0) {
+ if (pos->pmk_len == entry->pmk_len &&
+ os_memcmp_const(pos->pmk, entry->pmk,
+ entry->pmk_len) == 0 &&
os_memcmp_const(pos->pmkid, entry->pmkid,
PMKID_LEN) == 0) {
wpa_printf(MSG_DEBUG, "WPA: reusing previous "
@@ -194,8 +213,8 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
"the current AP and any PMKSA cache entry "
"that was based on the old PMK");
if (!pos->opportunistic)
- pmksa_cache_flush(pmksa, network_ctx, pos->pmk,
- pos->pmk_len);
+ pmksa_cache_flush(pmksa, entry->network_ctx,
+ pos->pmk, pos->pmk_len);
pmksa_cache_free_entry(pmksa, pos, PMKSA_REPLACE);
break;
}
@@ -246,8 +265,11 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
}
pmksa->pmksa_count++;
wpa_printf(MSG_DEBUG, "RSN: Added PMKSA cache entry for " MACSTR
- " network_ctx=%p", MAC2STR(entry->aa), network_ctx);
- wpa_sm_add_pmkid(pmksa->sm, entry->aa, entry->pmkid);
+ " network_ctx=%p akmp=0x%x", MAC2STR(entry->aa),
+ entry->network_ctx, entry->akmp);
+ wpa_sm_add_pmkid(pmksa->sm, entry->network_ctx, entry->aa, entry->pmkid,
+ entry->fils_cache_id_set ? entry->fils_cache_id : NULL,
+ entry->pmk, entry->pmk_len);
return entry;
}
@@ -322,17 +344,20 @@ void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa)
* @aa: Authenticator address or %NULL to match any
* @pmkid: PMKID or %NULL to match any
* @network_ctx: Network context or %NULL to match any
+ * @akmp: Specific AKMP to search for or 0 for any
* Returns: Pointer to PMKSA cache entry or %NULL if no match was found
*/
struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa,
const u8 *aa, const u8 *pmkid,
- const void *network_ctx)
+ const void *network_ctx,
+ int akmp)
{
struct rsn_pmksa_cache_entry *entry = pmksa->pmksa;
while (entry) {
if ((aa == NULL || os_memcmp(entry->aa, aa, ETH_ALEN) == 0) &&
(pmkid == NULL ||
os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0) &&
+ (!akmp || akmp == entry->akmp) &&
(network_ctx == NULL || network_ctx == entry->network_ctx))
return entry;
entry = entry->next;
@@ -347,16 +372,19 @@ pmksa_cache_clone_entry(struct rsn_pmksa_cache *pmksa,
const u8 *aa)
{
struct rsn_pmksa_cache_entry *new_entry;
+ os_time_t old_expiration = old_entry->expiration;
new_entry = pmksa_cache_add(pmksa, old_entry->pmk, old_entry->pmk_len,
NULL, NULL, 0,
aa, pmksa->sm->own_addr,
- old_entry->network_ctx, old_entry->akmp);
+ old_entry->network_ctx, old_entry->akmp,
+ old_entry->fils_cache_id_set ?
+ old_entry->fils_cache_id : NULL);
if (new_entry == NULL)
return NULL;
/* TODO: reorder entries based on expiration time? */
- new_entry->expiration = old_entry->expiration;
+ new_entry->expiration = old_expiration;
new_entry->opportunistic = 1;
return new_entry;
@@ -368,6 +396,7 @@ pmksa_cache_clone_entry(struct rsn_pmksa_cache *pmksa,
* @pmksa: Pointer to PMKSA cache data from pmksa_cache_init()
* @network_ctx: Network configuration context
* @aa: Authenticator address for the new AP
+ * @akmp: Specific AKMP to search for or 0 for any
* Returns: Pointer to a new PMKSA cache entry or %NULL if not available
*
* Try to create a new PMKSA cache entry opportunistically by guessing that the
@@ -376,7 +405,7 @@ pmksa_cache_clone_entry(struct rsn_pmksa_cache *pmksa,
*/
struct rsn_pmksa_cache_entry *
pmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa, void *network_ctx,
- const u8 *aa)
+ const u8 *aa, int akmp)
{
struct rsn_pmksa_cache_entry *entry = pmksa->pmksa;
@@ -384,7 +413,8 @@ pmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa, void *network_ctx,
if (network_ctx == NULL)
return NULL;
while (entry) {
- if (entry->network_ctx == network_ctx) {
+ if (entry->network_ctx == network_ctx &&
+ (!akmp || entry->akmp == akmp)) {
entry = pmksa_cache_clone_entry(pmksa, entry, aa);
if (entry) {
wpa_printf(MSG_DEBUG, "RSN: added "
@@ -399,6 +429,24 @@ pmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa, void *network_ctx,
}
+static struct rsn_pmksa_cache_entry *
+pmksa_cache_get_fils_cache_id(struct rsn_pmksa_cache *pmksa,
+ const void *network_ctx, const u8 *cache_id)
+{
+ struct rsn_pmksa_cache_entry *entry;
+
+ for (entry = pmksa->pmksa; entry; entry = entry->next) {
+ if (network_ctx == entry->network_ctx &&
+ entry->fils_cache_id_set &&
+ os_memcmp(cache_id, entry->fils_cache_id,
+ FILS_CACHE_ID_LEN) == 0)
+ return entry;
+ }
+
+ return NULL;
+}
+
+
/**
* pmksa_cache_get_current - Get the current used PMKSA entry
* @sm: Pointer to WPA state machine data from wpa_sm_init()
@@ -431,33 +479,44 @@ void pmksa_cache_clear_current(struct wpa_sm *sm)
* @bssid: BSSID for PMKSA or %NULL if not used
* @network_ctx: Network configuration context
* @try_opportunistic: Whether to allow opportunistic PMKSA caching
+ * @fils_cache_id: Pointer to FILS Cache Identifier or %NULL if not used
* Returns: 0 if PMKSA was found or -1 if no matching entry was found
*/
int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid,
const u8 *bssid, void *network_ctx,
- int try_opportunistic)
+ int try_opportunistic, const u8 *fils_cache_id,
+ int akmp)
{
struct rsn_pmksa_cache *pmksa = sm->pmksa;
wpa_printf(MSG_DEBUG, "RSN: PMKSA cache search - network_ctx=%p "
- "try_opportunistic=%d", network_ctx, try_opportunistic);
+ "try_opportunistic=%d akmp=0x%x",
+ network_ctx, try_opportunistic, akmp);
if (pmkid)
wpa_hexdump(MSG_DEBUG, "RSN: Search for PMKID",
pmkid, PMKID_LEN);
if (bssid)
wpa_printf(MSG_DEBUG, "RSN: Search for BSSID " MACSTR,
MAC2STR(bssid));
+ if (fils_cache_id)
+ wpa_printf(MSG_DEBUG,
+ "RSN: Search for FILS Cache Identifier %02x%02x",
+ fils_cache_id[0], fils_cache_id[1]);
sm->cur_pmksa = NULL;
if (pmkid)
sm->cur_pmksa = pmksa_cache_get(pmksa, NULL, pmkid,
- network_ctx);
+ network_ctx, akmp);
if (sm->cur_pmksa == NULL && bssid)
sm->cur_pmksa = pmksa_cache_get(pmksa, bssid, NULL,
- network_ctx);
+ network_ctx, akmp);
if (sm->cur_pmksa == NULL && try_opportunistic && bssid)
sm->cur_pmksa = pmksa_cache_get_opportunistic(pmksa,
network_ctx,
- bssid);
+ bssid, akmp);
+ if (sm->cur_pmksa == NULL && fils_cache_id)
+ sm->cur_pmksa = pmksa_cache_get_fils_cache_id(pmksa,
+ network_ctx,
+ fils_cache_id);
if (sm->cur_pmksa) {
wpa_hexdump(MSG_DEBUG, "RSN: PMKSA cache entry found - PMKID",
sm->cur_pmksa->pmkid, PMKID_LEN);
@@ -484,11 +543,20 @@ int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len)
char *pos = buf;
struct rsn_pmksa_cache_entry *entry;
struct os_reltime now;
+ int cache_id_used = 0;
+
+ for (entry = pmksa->pmksa; entry; entry = entry->next) {
+ if (entry->fils_cache_id_set) {
+ cache_id_used = 1;
+ break;
+ }
+ }
os_get_reltime(&now);
ret = os_snprintf(pos, buf + len - pos,
"Index / AA / PMKID / expiration (in seconds) / "
- "opportunistic\n");
+ "opportunistic%s\n",
+ cache_id_used ? " / FILS Cache Identifier" : "");
if (os_snprintf_error(buf + len - pos, ret))
return pos - buf;
pos += ret;
@@ -503,18 +571,36 @@ int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len)
pos += ret;
pos += wpa_snprintf_hex(pos, buf + len - pos, entry->pmkid,
PMKID_LEN);
- ret = os_snprintf(pos, buf + len - pos, " %d %d\n",
+ ret = os_snprintf(pos, buf + len - pos, " %d %d",
(int) (entry->expiration - now.sec),
entry->opportunistic);
if (os_snprintf_error(buf + len - pos, ret))
return pos - buf;
pos += ret;
+ if (entry->fils_cache_id_set) {
+ ret = os_snprintf(pos, buf + len - pos, " %02x%02x",
+ entry->fils_cache_id[0],
+ entry->fils_cache_id[1]);
+ if (os_snprintf_error(buf + len - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+ ret = os_snprintf(pos, buf + len - pos, "\n");
+ if (os_snprintf_error(buf + len - pos, ret))
+ return pos - buf;
+ pos += ret;
entry = entry->next;
}
return pos - buf;
}
+struct rsn_pmksa_cache_entry * pmksa_cache_head(struct rsn_pmksa_cache *pmksa)
+{
+ return pmksa->pmksa;
+}
+
+
/**
* pmksa_cache_init - Initialize PMKSA cache
* @free_cb: Callback function to be called when a PMKSA cache entry is freed
diff --git a/freebsd/contrib/wpa/src/rsn_supp/pmksa_cache.h b/freebsd/contrib/wpa/src/rsn_supp/pmksa_cache.h
index daede6da..6c49fa92 100644
--- a/freebsd/contrib/wpa/src/rsn_supp/pmksa_cache.h
+++ b/freebsd/contrib/wpa/src/rsn_supp/pmksa_cache.h
@@ -21,6 +21,14 @@ struct rsn_pmksa_cache_entry {
int akmp; /* WPA_KEY_MGMT_* */
u8 aa[ETH_ALEN];
+ /*
+ * If FILS Cache Identifier is included (fils_cache_id_set), this PMKSA
+ * cache entry is applicable to all BSSs (any BSSID/aa[]) that
+ * advertise the same FILS Cache Identifier within the same ESS.
+ */
+ u8 fils_cache_id[2];
+ unsigned int fils_cache_id_set:1;
+
os_time_t reauth_time;
/**
@@ -53,20 +61,27 @@ pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry,
void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa);
struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa,
const u8 *aa, const u8 *pmkid,
- const void *network_ctx);
+ const void *network_ctx,
+ int akmp);
int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len);
+struct rsn_pmksa_cache_entry * pmksa_cache_head(struct rsn_pmksa_cache *pmksa);
struct rsn_pmksa_cache_entry *
pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
const u8 *pmkid, const u8 *kck, size_t kck_len,
- const u8 *aa, const u8 *spa, void *network_ctx, int akmp);
+ const u8 *aa, const u8 *spa, void *network_ctx, int akmp,
+ const u8 *cache_id);
+struct rsn_pmksa_cache_entry *
+pmksa_cache_add_entry(struct rsn_pmksa_cache *pmksa,
+ struct rsn_pmksa_cache_entry *entry);
struct rsn_pmksa_cache_entry * pmksa_cache_get_current(struct wpa_sm *sm);
void pmksa_cache_clear_current(struct wpa_sm *sm);
int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid,
const u8 *bssid, void *network_ctx,
- int try_opportunistic);
+ int try_opportunistic, const u8 *fils_cache_id,
+ int akmp);
struct rsn_pmksa_cache_entry *
pmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa,
- void *network_ctx, const u8 *aa);
+ void *network_ctx, const u8 *aa, int akmp);
void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx,
const u8 *pmk, size_t pmk_len);
@@ -86,7 +101,7 @@ static inline void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa)
static inline struct rsn_pmksa_cache_entry *
pmksa_cache_get(struct rsn_pmksa_cache *pmksa, const u8 *aa, const u8 *pmkid,
- const void *network_ctx)
+ const void *network_ctx, int akmp)
{
return NULL;
}
@@ -104,9 +119,23 @@ static inline int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf,
}
static inline struct rsn_pmksa_cache_entry *
+pmksa_cache_head(struct rsn_pmksa_cache *pmksa)
+{
+ return NULL;
+}
+
+static inline struct rsn_pmksa_cache_entry *
+pmksa_cache_add_entry(struct rsn_pmksa_cache *pmksa,
+ struct rsn_pmksa_cache_entry *entry)
+{
+ return NULL;
+}
+
+static inline struct rsn_pmksa_cache_entry *
pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
const u8 *pmkid, const u8 *kck, size_t kck_len,
- const u8 *aa, const u8 *spa, void *network_ctx, int akmp)
+ const u8 *aa, const u8 *spa, void *network_ctx, int akmp,
+ const u8 *cache_id)
{
return NULL;
}
@@ -118,7 +147,9 @@ static inline void pmksa_cache_clear_current(struct wpa_sm *sm)
static inline int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid,
const u8 *bssid,
void *network_ctx,
- int try_opportunistic)
+ int try_opportunistic,
+ const u8 *fils_cache_id,
+ int akmp)
{
return -1;
}
diff --git a/freebsd/contrib/wpa/src/rsn_supp/preauth.c b/freebsd/contrib/wpa/src/rsn_supp/preauth.c
index 470f5971..ff8dee40 100644
--- a/freebsd/contrib/wpa/src/rsn_supp/preauth.c
+++ b/freebsd/contrib/wpa/src/rsn_supp/preauth.c
@@ -99,7 +99,7 @@ static void rsn_preauth_eapol_cb(struct eapol_sm *eapol,
NULL, 0,
sm->preauth_bssid, sm->own_addr,
sm->network_ctx,
- WPA_KEY_MGMT_IEEE8021X);
+ WPA_KEY_MGMT_IEEE8021X, NULL);
} else {
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
"RSN: failed to get master session key from "
@@ -325,7 +325,7 @@ void rsn_preauth_candidate_process(struct wpa_sm *sm)
dl_list_for_each_safe(candidate, n, &sm->pmksa_candidates,
struct rsn_pmksa_candidate, list) {
struct rsn_pmksa_cache_entry *p = NULL;
- p = pmksa_cache_get(sm->pmksa, candidate->bssid, NULL, NULL);
+ p = pmksa_cache_get(sm->pmksa, candidate->bssid, NULL, NULL, 0);
if (os_memcmp(sm->bssid, candidate->bssid, ETH_ALEN) != 0 &&
(p == NULL || p->opportunistic)) {
wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA "
@@ -344,7 +344,8 @@ void rsn_preauth_candidate_process(struct wpa_sm *sm)
/* Some drivers (e.g., NDIS) expect to get notified about the
* PMKIDs again, so report the existing data now. */
if (p) {
- wpa_sm_add_pmkid(sm, candidate->bssid, p->pmkid);
+ wpa_sm_add_pmkid(sm, NULL, candidate->bssid, p->pmkid,
+ NULL, p->pmk, p->pmk_len);
}
dl_list_del(&candidate->list);
@@ -373,7 +374,7 @@ void pmksa_candidate_add(struct wpa_sm *sm, const u8 *bssid,
if (sm->network_ctx && sm->proactive_key_caching)
pmksa_cache_get_opportunistic(sm->pmksa, sm->network_ctx,
- bssid);
+ bssid, 0);
if (!preauth) {
wpa_printf(MSG_DEBUG, "RSN: Ignored PMKID candidate without "
@@ -484,7 +485,7 @@ void rsn_preauth_scan_result(struct wpa_sm *sm, const u8 *bssid,
if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie))
return;
- pmksa = pmksa_cache_get(sm->pmksa, bssid, NULL, NULL);
+ pmksa = pmksa_cache_get(sm->pmksa, bssid, NULL, NULL, 0);
if (pmksa && (!pmksa->opportunistic ||
!(ie.capabilities & WPA_CAPABILITY_PREAUTH)))
return;
diff --git a/freebsd/contrib/wpa/src/rsn_supp/wpa.c b/freebsd/contrib/wpa/src/rsn_supp/wpa.c
index 4ad6bb6a..c2ebec54 100644
--- a/freebsd/contrib/wpa/src/rsn_supp/wpa.c
+++ b/freebsd/contrib/wpa/src/rsn_supp/wpa.c
@@ -2,7 +2,7 @@
/*
* WPA Supplicant - WPA state machine and EAPOL-Key processing
- * Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2018, Jouni Malinen <j@w1.fi>
* Copyright(c) 2015 Intel Deutschland GmbH
*
* This software may be distributed under the terms of the BSD license.
@@ -12,18 +12,26 @@
#include "includes.h"
#include "common.h"
+#include "crypto/aes.h"
#include "crypto/aes_wrap.h"
#include "crypto/crypto.h"
#include "crypto/random.h"
+#include "crypto/aes_siv.h"
+#include "crypto/sha256.h"
+#include "crypto/sha384.h"
+#include "crypto/sha512.h"
#include "common/ieee802_11_defs.h"
+#include "common/ieee802_11_common.h"
+#include "common/ocv.h"
+#include "eap_common/eap_defs.h"
#include "eapol_supp/eapol_supp_sm.h"
+#include "drivers/driver.h"
#include "wpa.h"
#include "eloop.h"
#include "preauth.h"
#include "pmksa_cache.h"
#include "wpa_i.h"
#include "wpa_ie.h"
-#include "peerkey.h"
static const u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
@@ -32,8 +40,7 @@ static const u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
/**
* wpa_eapol_key_send - Send WPA/RSN EAPOL-Key message
* @sm: Pointer to WPA state machine data from wpa_sm_init()
- * @kck: Key Confirmation Key (KCK, part of PTK)
- * @kck_len: KCK length in octets
+ * @ptk: PTK for Key Confirmation/Encryption Key
* @ver: Version field from Key Info
* @dest: Destination address for the frame
* @proto: Ethertype (usually ETH_P_EAPOL)
@@ -42,13 +49,16 @@ static const u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
* @key_mic: Pointer to the buffer to which the EAPOL-Key MIC is written
* Returns: >= 0 on success, < 0 on failure
*/
-int wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, size_t kck_len,
+int wpa_eapol_key_send(struct wpa_sm *sm, struct wpa_ptk *ptk,
int ver, const u8 *dest, u16 proto,
u8 *msg, size_t msg_len, u8 *key_mic)
{
int ret = -1;
- size_t mic_len = wpa_mic_len(sm->key_mgmt);
+ size_t mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len);
+ wpa_printf(MSG_DEBUG, "WPA: Send EAPOL-Key frame to " MACSTR
+ " ver=%d mic_len=%d key_mgmt=0x%x",
+ MAC2STR(dest), ver, (int) mic_len, sm->key_mgmt);
if (is_zero_ether_addr(dest) && is_zero_ether_addr(sm->bssid)) {
/*
* Association event was not yet received; try to fetch
@@ -66,16 +76,89 @@ int wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, size_t kck_len,
MAC2STR(dest));
}
}
- if (key_mic &&
- wpa_eapol_key_mic(kck, kck_len, sm->key_mgmt, ver, msg, msg_len,
- key_mic)) {
- wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
- "WPA: Failed to generate EAPOL-Key version %d key_mgmt 0x%x MIC",
- ver, sm->key_mgmt);
+
+ if (mic_len) {
+ if (key_mic && (!ptk || !ptk->kck_len))
+ goto out;
+
+ if (key_mic &&
+ wpa_eapol_key_mic(ptk->kck, ptk->kck_len, sm->key_mgmt, ver,
+ msg, msg_len, key_mic)) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
+ "WPA: Failed to generate EAPOL-Key version %d key_mgmt 0x%x MIC",
+ ver, sm->key_mgmt);
+ goto out;
+ }
+ if (ptk)
+ wpa_hexdump_key(MSG_DEBUG, "WPA: KCK",
+ ptk->kck, ptk->kck_len);
+ wpa_hexdump(MSG_DEBUG, "WPA: Derived Key MIC",
+ key_mic, mic_len);
+ } else {
+#ifdef CONFIG_FILS
+ /* AEAD cipher - Key MIC field not used */
+ struct ieee802_1x_hdr *s_hdr, *hdr;
+ struct wpa_eapol_key *s_key, *key;
+ u8 *buf, *s_key_data, *key_data;
+ size_t buf_len = msg_len + AES_BLOCK_SIZE;
+ size_t key_data_len;
+ u16 eapol_len;
+ const u8 *aad[1];
+ size_t aad_len[1];
+
+ if (!ptk || !ptk->kek_len)
+ goto out;
+
+ key_data_len = msg_len - sizeof(struct ieee802_1x_hdr) -
+ sizeof(struct wpa_eapol_key) - 2;
+
+ buf = os_malloc(buf_len);
+ if (!buf)
+ goto out;
+
+ os_memcpy(buf, msg, msg_len);
+ hdr = (struct ieee802_1x_hdr *) buf;
+ key = (struct wpa_eapol_key *) (hdr + 1);
+ key_data = ((u8 *) (key + 1)) + 2;
+
+ /* Update EAPOL header to include AES-SIV overhead */
+ eapol_len = be_to_host16(hdr->length);
+ eapol_len += AES_BLOCK_SIZE;
+ hdr->length = host_to_be16(eapol_len);
+
+ /* Update Key Data Length field to include AES-SIV overhead */
+ WPA_PUT_BE16((u8 *) (key + 1), AES_BLOCK_SIZE + key_data_len);
+
+ s_hdr = (struct ieee802_1x_hdr *) msg;
+ s_key = (struct wpa_eapol_key *) (s_hdr + 1);
+ s_key_data = ((u8 *) (s_key + 1)) + 2;
+
+ wpa_hexdump_key(MSG_DEBUG, "WPA: Plaintext Key Data",
+ s_key_data, key_data_len);
+
+ wpa_hexdump_key(MSG_DEBUG, "WPA: KEK", ptk->kek, ptk->kek_len);
+ /* AES-SIV AAD from EAPOL protocol version field (inclusive) to
+ * to Key Data (exclusive). */
+ aad[0] = buf;
+ aad_len[0] = key_data - buf;
+ if (aes_siv_encrypt(ptk->kek, ptk->kek_len,
+ s_key_data, key_data_len,
+ 1, aad, aad_len, key_data) < 0) {
+ os_free(buf);
+ goto out;
+ }
+
+ wpa_hexdump(MSG_DEBUG, "WPA: Encrypted Key Data from SIV",
+ key_data, AES_BLOCK_SIZE + key_data_len);
+
+ os_free(msg);
+ msg = buf;
+ msg_len = buf_len;
+#else /* CONFIG_FILS */
goto out;
+#endif /* CONFIG_FILS */
}
- wpa_hexdump_key(MSG_DEBUG, "WPA: KCK", kck, kck_len);
- wpa_hexdump(MSG_DEBUG, "WPA: Derived Key MIC", key_mic, mic_len);
+
wpa_hexdump(MSG_MSGDUMP, "WPA: TX EAPOL-Key", msg, msg_len);
ret = wpa_sm_ether_send(sm, dest, proto, msg, msg_len);
eapol_sm_notify_tx_eapol_key(sm->eapol);
@@ -99,12 +182,10 @@ void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise)
{
size_t mic_len, hdrlen, rlen;
struct wpa_eapol_key *reply;
- struct wpa_eapol_key_192 *reply192;
int key_info, ver;
- u8 bssid[ETH_ALEN], *rbuf, *key_mic;
+ u8 bssid[ETH_ALEN], *rbuf, *key_mic, *mic;
- if (sm->key_mgmt == WPA_KEY_MGMT_OSEN ||
- wpa_key_mgmt_suite_b(sm->key_mgmt))
+ if (wpa_use_akm_defined(sm->key_mgmt))
ver = WPA_KEY_INFO_TYPE_AKM_DEFINED;
else if (wpa_key_mgmt_ft(sm->key_mgmt) ||
wpa_key_mgmt_sha256(sm->key_mgmt))
@@ -120,20 +201,21 @@ void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise)
return;
}
- mic_len = wpa_mic_len(sm->key_mgmt);
- hdrlen = mic_len == 24 ? sizeof(*reply192) : sizeof(*reply);
+ mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len);
+ hdrlen = sizeof(*reply) + mic_len + 2;
rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
hdrlen, &rlen, (void *) &reply);
if (rbuf == NULL)
return;
- reply192 = (struct wpa_eapol_key_192 *) reply;
reply->type = (sm->proto == WPA_PROTO_RSN ||
sm->proto == WPA_PROTO_OSEN) ?
EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
key_info = WPA_KEY_INFO_REQUEST | ver;
if (sm->ptk_set)
- key_info |= WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE;
+ key_info |= WPA_KEY_INFO_SECURE;
+ if (sm->ptk_set && mic_len)
+ key_info |= WPA_KEY_INFO_MIC;
if (error)
key_info |= WPA_KEY_INFO_ERROR;
if (pairwise)
@@ -144,21 +226,19 @@ void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise)
WPA_REPLAY_COUNTER_LEN);
inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN);
- if (mic_len == 24)
- WPA_PUT_BE16(reply192->key_data_length, 0);
- else
- WPA_PUT_BE16(reply->key_data_length, 0);
+ mic = (u8 *) (reply + 1);
+ WPA_PUT_BE16(mic + mic_len, 0);
if (!(key_info & WPA_KEY_INFO_MIC))
key_mic = NULL;
else
- key_mic = reply192->key_mic; /* same offset in reply */
+ key_mic = mic;
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
"WPA: Sending EAPOL-Key Request (error=%d "
"pairwise=%d ptk_set=%d len=%lu)",
error, pairwise, sm->ptk_set, (unsigned long) rlen);
- wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, bssid,
- ETH_P_EAPOL, rbuf, rlen, key_mic);
+ wpa_eapol_key_send(sm, &sm->ptk, ver, bssid, ETH_P_EAPOL, rbuf, rlen,
+ key_mic);
}
@@ -192,7 +272,7 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm,
* event before receiving this 1/4 message, so try to find a
* matching PMKSA cache entry here. */
sm->cur_pmksa = pmksa_cache_get(sm->pmksa, src_addr, pmkid,
- NULL);
+ NULL, 0);
if (sm->cur_pmksa) {
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
"RSN: found matching PMKID from PMKSA cache");
@@ -212,11 +292,23 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm,
eapol_sm_notify_cached(sm->eapol);
#ifdef CONFIG_IEEE80211R
sm->xxkey_len = 0;
+#ifdef CONFIG_SAE
+ if (sm->key_mgmt == WPA_KEY_MGMT_FT_SAE &&
+ sm->pmk_len == PMK_LEN) {
+ /* Need to allow FT key derivation to proceed with
+ * PMK from SAE being used as the XXKey in cases where
+ * the PMKID in msg 1/4 matches the PMKSA entry that was
+ * just added based on SAE authentication for the
+ * initial mobility domain association. */
+ os_memcpy(sm->xxkey, sm->pmk, sm->pmk_len);
+ sm->xxkey_len = sm->pmk_len;
+ }
+#endif /* CONFIG_SAE */
#endif /* CONFIG_IEEE80211R */
} else if (wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt) && sm->eapol) {
int res, pmk_len;
- if (sm->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
+ if (wpa_key_mgmt_sha384(sm->key_mgmt))
pmk_len = PMK_LEN_SUITE_B_192;
else
pmk_len = PMK_LEN;
@@ -235,14 +327,28 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm,
u8 buf[2 * PMK_LEN];
if (eapol_sm_get_key(sm->eapol, buf, 2 * PMK_LEN) == 0)
{
- os_memcpy(sm->xxkey, buf + PMK_LEN, PMK_LEN);
- sm->xxkey_len = PMK_LEN;
+ if (wpa_key_mgmt_sha384(sm->key_mgmt)) {
+ os_memcpy(sm->xxkey, buf,
+ SHA384_MAC_LEN);
+ sm->xxkey_len = SHA384_MAC_LEN;
+ } else {
+ os_memcpy(sm->xxkey, buf + PMK_LEN,
+ PMK_LEN);
+ sm->xxkey_len = PMK_LEN;
+ }
os_memset(buf, 0, sizeof(buf));
}
#endif /* CONFIG_IEEE80211R */
}
if (res == 0) {
struct rsn_pmksa_cache_entry *sa = NULL;
+ const u8 *fils_cache_id = NULL;
+
+#ifdef CONFIG_FILS
+ if (sm->fils_cache_id_set)
+ fils_cache_id = sm->fils_cache_id;
+#endif /* CONFIG_FILS */
+
wpa_hexdump_key(MSG_DEBUG, "WPA: PMK from EAPOL state "
"machines", sm->pmk, pmk_len);
sm->pmk_len = pmk_len;
@@ -255,11 +361,12 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm,
NULL, 0,
src_addr, sm->own_addr,
sm->network_ctx,
- sm->key_mgmt);
+ sm->key_mgmt,
+ fils_cache_id);
}
if (!sm->cur_pmksa && pmkid &&
- pmksa_cache_get(sm->pmksa, src_addr, pmkid, NULL))
- {
+ pmksa_cache_get(sm->pmksa, src_addr, pmkid, NULL,
+ 0)) {
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
"RSN: the new PMK matches with the "
"PMKID");
@@ -279,6 +386,11 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm,
if (!sm->cur_pmksa)
sm->cur_pmksa = sa;
+#ifdef CONFIG_IEEE80211R
+ } else if (wpa_key_mgmt_ft(sm->key_mgmt) && sm->ft_protocol) {
+ wpa_printf(MSG_DEBUG,
+ "FT: Continue 4-way handshake without PMK/PMKID for association using FT protocol");
+#endif /* CONFIG_IEEE80211R */
} else {
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
"WPA: Failed to get master session key from "
@@ -343,9 +455,9 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
{
size_t mic_len, hdrlen, rlen;
struct wpa_eapol_key *reply;
- struct wpa_eapol_key_192 *reply192;
u8 *rbuf, *key_mic;
u8 *rsn_ie_buf = NULL;
+ u16 key_info;
if (wpa_ie == NULL) {
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: No wpa_ie set - "
@@ -385,8 +497,8 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
wpa_hexdump(MSG_DEBUG, "WPA: WPA IE for msg 2/4", wpa_ie, wpa_ie_len);
- mic_len = wpa_mic_len(sm->key_mgmt);
- hdrlen = mic_len == 24 ? sizeof(*reply192) : sizeof(*reply);
+ mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len);
+ hdrlen = sizeof(*reply) + mic_len + 2;
rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY,
NULL, hdrlen + wpa_ie_len,
&rlen, (void *) &reply);
@@ -394,13 +506,16 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
os_free(rsn_ie_buf);
return -1;
}
- reply192 = (struct wpa_eapol_key_192 *) reply;
reply->type = (sm->proto == WPA_PROTO_RSN ||
sm->proto == WPA_PROTO_OSEN) ?
EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
- WPA_PUT_BE16(reply->key_info,
- ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC);
+ key_info = ver | WPA_KEY_INFO_KEY_TYPE;
+ if (mic_len)
+ key_info |= WPA_KEY_INFO_MIC;
+ else
+ key_info |= WPA_KEY_INFO_ENCR_KEY_DATA;
+ WPA_PUT_BE16(reply->key_info, key_info);
if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN)
WPA_PUT_BE16(reply->key_length, 0);
else
@@ -410,36 +525,41 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
wpa_hexdump(MSG_DEBUG, "WPA: Replay Counter", reply->replay_counter,
WPA_REPLAY_COUNTER_LEN);
- key_mic = reply192->key_mic; /* same offset for reply and reply192 */
- if (mic_len == 24) {
- WPA_PUT_BE16(reply192->key_data_length, wpa_ie_len);
- os_memcpy(reply192 + 1, wpa_ie, wpa_ie_len);
- } else {
- WPA_PUT_BE16(reply->key_data_length, wpa_ie_len);
- os_memcpy(reply + 1, wpa_ie, wpa_ie_len);
- }
+ key_mic = (u8 *) (reply + 1);
+ WPA_PUT_BE16(key_mic + mic_len, wpa_ie_len); /* Key Data Length */
+ os_memcpy(key_mic + mic_len + 2, wpa_ie, wpa_ie_len); /* Key Data */
os_free(rsn_ie_buf);
os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN);
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/4");
- return wpa_eapol_key_send(sm, ptk->kck, ptk->kck_len, ver, dst,
- ETH_P_EAPOL, rbuf, rlen, key_mic);
+ return wpa_eapol_key_send(sm, ptk, ver, dst, ETH_P_EAPOL, rbuf, rlen,
+ key_mic);
}
static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr,
const struct wpa_eapol_key *key, struct wpa_ptk *ptk)
{
+ const u8 *z = NULL;
+ size_t z_len = 0;
+
#ifdef CONFIG_IEEE80211R
if (wpa_key_mgmt_ft(sm->key_mgmt))
return wpa_derive_ptk_ft(sm, src_addr, key, ptk);
#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_DPP2
+ if (sm->key_mgmt == WPA_KEY_MGMT_DPP && sm->dpp_z) {
+ z = wpabuf_head(sm->dpp_z);
+ z_len = wpabuf_len(sm->dpp_z);
+ }
+#endif /* CONFIG_DPP2 */
+
return wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion",
sm->own_addr, sm->bssid, sm->snonce,
key->key_nonce, ptk, sm->key_mgmt,
- sm->pairwise_cipher);
+ sm->pairwise_cipher, z, z_len);
}
@@ -502,7 +622,8 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm,
/* Calculate PTK which will be stored as a temporary PTK until it has
* been verified when processing message 3/4. */
ptk = &sm->tptk;
- wpa_derive_ptk(sm, src_addr, key, ptk);
+ if (wpa_derive_ptk(sm, src_addr, key, ptk) < 0)
+ goto failed;
if (sm->pairwise_cipher == WPA_CIPHER_TKIP) {
u8 buf[8];
/* Supplicant: swap tx/rx Mic keys */
@@ -516,6 +637,33 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm,
kde = sm->assoc_wpa_ie;
kde_len = sm->assoc_wpa_ie_len;
+#ifdef CONFIG_OCV
+ if (wpa_sm_ocv_enabled(sm)) {
+ struct wpa_channel_info ci;
+ u8 *pos;
+
+ if (wpa_sm_channel_info(sm, &ci) != 0) {
+ wpa_printf(MSG_WARNING,
+ "Failed to get channel info for OCI element in EAPOL-Key 2/4");
+ goto failed;
+ }
+
+ kde_buf = os_malloc(kde_len + 2 + RSN_SELECTOR_LEN + 3);
+ if (!kde_buf) {
+ wpa_printf(MSG_WARNING,
+ "Failed to allocate memory for KDE with OCI in EAPOL-Key 2/4");
+ goto failed;
+ }
+
+ os_memcpy(kde_buf, kde, kde_len);
+ kde = kde_buf;
+ pos = kde + kde_len;
+ if (ocv_insert_oci_kde(&ci, &pos) < 0)
+ goto failed;
+ kde_len = pos - kde;
+ }
+#endif /* CONFIG_OCV */
+
#ifdef CONFIG_P2P
if (sm->p2p) {
kde_buf = os_malloc(kde_len + 2 + RSN_SELECTOR_LEN + 1);
@@ -573,7 +721,9 @@ static void wpa_supplicant_key_neg_complete(struct wpa_sm *sm,
sm, addr, MLME_SETPROTECTION_PROTECT_TYPE_RX_TX,
MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
eapol_sm_notify_portValid(sm->eapol, TRUE);
- if (wpa_key_mgmt_wpa_psk(sm->key_mgmt))
+ if (wpa_key_mgmt_wpa_psk(sm->key_mgmt) ||
+ sm->key_mgmt == WPA_KEY_MGMT_DPP ||
+ sm->key_mgmt == WPA_KEY_MGMT_OWE)
eapol_sm_notify_eap_success(sm->eapol, TRUE);
/*
* Start preauthentication after a short wait to avoid a
@@ -582,7 +732,9 @@ static void wpa_supplicant_key_neg_complete(struct wpa_sm *sm,
* likelihood of the first preauth EAPOL-Start frame getting to
* the target AP.
*/
- eloop_register_timeout(1, 0, wpa_sm_start_preauth, sm, NULL);
+ if (!dl_list_empty(&sm->pmksa_candidates))
+ eloop_register_timeout(1, 0, wpa_sm_start_preauth,
+ sm, NULL);
}
if (sm->cur_pmksa && sm->cur_pmksa->opportunistic) {
@@ -640,6 +792,11 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *sm,
alg = wpa_cipher_to_alg(sm->pairwise_cipher);
keylen = wpa_cipher_key_len(sm->pairwise_cipher);
+ if (keylen <= 0 || (unsigned int) keylen != sm->ptk.tk_len) {
+ wpa_printf(MSG_DEBUG, "WPA: TK length mismatch: %d != %lu",
+ keylen, (long unsigned int) sm->ptk.tk_len);
+ return -1;
+ }
rsclen = wpa_cipher_rsc_len(sm->pairwise_cipher);
if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) {
@@ -660,6 +817,7 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *sm,
/* TK is not needed anymore in supplicant */
os_memset(sm->ptk.tk, 0, WPA_TK_MAX_LEN);
+ sm->ptk.tk_len = 0;
sm->ptk.installed = 1;
if (sm->wpa_ptk_rekey) {
@@ -870,8 +1028,6 @@ static int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm,
}
os_memset(&gd, 0, sizeof(gd));
- wpa_supplicant_key_neg_complete(sm, sm->bssid,
- key_info & WPA_KEY_INFO_SECURE);
return 0;
}
@@ -897,7 +1053,7 @@ static int wpa_supplicant_install_igtk(struct wpa_sm *sm,
}
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
- "WPA: IGTK keyid %d pn %02x%02x%02x%02x%02x%02x",
+ "WPA: IGTK keyid %d pn " COMPACT_MACSTR,
keyidx, MAC2STR(igtk->pn));
wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK", igtk->igtk, len);
if (keyidx > 4095) {
@@ -909,9 +1065,27 @@ static int wpa_supplicant_install_igtk(struct wpa_sm *sm,
broadcast_ether_addr,
keyidx, 0, igtk->pn, sizeof(igtk->pn),
igtk->igtk, len) < 0) {
- wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
- "WPA: Failed to configure IGTK to the driver");
- return -1;
+ if (keyidx == 0x0400 || keyidx == 0x0500) {
+ /* Assume the AP has broken PMF implementation since it
+ * seems to have swapped the KeyID bytes. The AP cannot
+ * be trusted to implement BIP correctly or provide a
+ * valid IGTK, so do not try to configure this key with
+ * swapped KeyID bytes. Instead, continue without
+ * configuring the IGTK so that the driver can drop any
+ * received group-addressed robust management frames due
+ * to missing keys.
+ *
+ * Normally, this error behavior would result in us
+ * disconnecting, but there are number of deployed APs
+ * with this broken behavior, so as an interoperability
+ * workaround, allow the connection to proceed. */
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "WPA: Ignore IGTK configuration error due to invalid IGTK KeyID byte order");
+ } else {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "WPA: Failed to configure IGTK to the driver");
+ return -1;
+ }
}
if (wnm_sleep) {
@@ -1205,22 +1379,24 @@ int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst,
{
size_t mic_len, hdrlen, rlen;
struct wpa_eapol_key *reply;
- struct wpa_eapol_key_192 *reply192;
u8 *rbuf, *key_mic;
- mic_len = wpa_mic_len(sm->key_mgmt);
- hdrlen = mic_len == 24 ? sizeof(*reply192) : sizeof(*reply);
+ mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len);
+ hdrlen = sizeof(*reply) + mic_len + 2;
rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
hdrlen, &rlen, (void *) &reply);
if (rbuf == NULL)
return -1;
- reply192 = (struct wpa_eapol_key_192 *) reply;
reply->type = (sm->proto == WPA_PROTO_RSN ||
sm->proto == WPA_PROTO_OSEN) ?
EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
key_info &= WPA_KEY_INFO_SECURE;
- key_info |= ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC;
+ key_info |= ver | WPA_KEY_INFO_KEY_TYPE;
+ if (mic_len)
+ key_info |= WPA_KEY_INFO_MIC;
+ else
+ key_info |= WPA_KEY_INFO_ENCR_KEY_DATA;
WPA_PUT_BE16(reply->key_info, key_info);
if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN)
WPA_PUT_BE16(reply->key_length, 0);
@@ -1229,15 +1405,12 @@ int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst,
os_memcpy(reply->replay_counter, key->replay_counter,
WPA_REPLAY_COUNTER_LEN);
- key_mic = reply192->key_mic; /* same offset for reply and reply192 */
- if (mic_len == 24)
- WPA_PUT_BE16(reply192->key_data_length, 0);
- else
- WPA_PUT_BE16(reply->key_data_length, 0);
+ key_mic = (u8 *) (reply + 1);
+ WPA_PUT_BE16(key_mic + mic_len, 0);
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 4/4");
- return wpa_eapol_key_send(sm, ptk->kck, ptk->kck_len, ver, dst,
- ETH_P_EAPOL, rbuf, rlen, key_mic);
+ return wpa_eapol_key_send(sm, ptk, ver, dst, ETH_P_EAPOL, rbuf, rlen,
+ key_mic);
}
@@ -1309,6 +1482,26 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm,
}
#endif /* CONFIG_P2P */
+#ifdef CONFIG_OCV
+ if (wpa_sm_ocv_enabled(sm)) {
+ struct wpa_channel_info ci;
+
+ if (wpa_sm_channel_info(sm, &ci) != 0) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "Failed to get channel info to validate received OCI in EAPOL-Key 3/4");
+ return;
+ }
+
+ if (ocv_verify_tx_params(ie.oci, ie.oci_len, &ci,
+ channel_width_to_int(ci.chanwidth),
+ ci.seg1_idx) != 0) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "%s",
+ ocv_errorstr);
+ return;
+ }
+ }
+#endif /* CONFIG_OCV */
+
if (wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info,
&sm->ptk) < 0) {
goto failed;
@@ -1333,8 +1526,11 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm,
wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);
if (sm->group_cipher == WPA_CIPHER_GTK_NOT_USED) {
- wpa_supplicant_key_neg_complete(sm, sm->bssid,
- key_info & WPA_KEY_INFO_SECURE);
+ /* No GTK to be set to the driver */
+ } else if (!ie.gtk && sm->proto == WPA_PROTO_RSN) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "RSN: No GTK KDE included in EAPOL-Key msg 3/4");
+ goto failed;
} else if (ie.gtk &&
wpa_supplicant_pairwise_gtk(sm, key,
ie.gtk, ie.gtk_len, key_info) < 0) {
@@ -1349,16 +1545,26 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm,
goto failed;
}
+ if (sm->group_cipher == WPA_CIPHER_GTK_NOT_USED || ie.gtk)
+ wpa_supplicant_key_neg_complete(sm, sm->bssid,
+ key_info & WPA_KEY_INFO_SECURE);
+
if (ie.gtk)
wpa_sm_set_rekey_offload(sm);
- if (sm->proto == WPA_PROTO_RSN && wpa_key_mgmt_suite_b(sm->key_mgmt)) {
+ /* Add PMKSA cache entry for Suite B AKMs here since PMKID can be
+ * calculated only after KCK has been derived. Though, do not replace an
+ * existing PMKSA entry after each 4-way handshake (i.e., new KCK/PMKID)
+ * to avoid unnecessary changes of PMKID while continuing to use the
+ * same PMK. */
+ if (sm->proto == WPA_PROTO_RSN && wpa_key_mgmt_suite_b(sm->key_mgmt) &&
+ !sm->cur_pmksa) {
struct rsn_pmksa_cache_entry *sa;
sa = pmksa_cache_add(sm->pmksa, sm->pmk, sm->pmk_len, NULL,
sm->ptk.kck, sm->ptk.kck_len,
sm->bssid, sm->own_addr,
- sm->network_ctx, sm->key_mgmt);
+ sm->network_ctx, sm->key_mgmt, NULL);
if (!sm->cur_pmksa)
sm->cur_pmksa = sa;
}
@@ -1380,7 +1586,8 @@ static int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm,
int maxkeylen;
struct wpa_eapol_ie_parse ie;
- wpa_hexdump(MSG_DEBUG, "RSN: msg 1/2 key data", keydata, keydatalen);
+ wpa_hexdump_key(MSG_DEBUG, "RSN: msg 1/2 key data",
+ keydata, keydatalen);
if (wpa_supplicant_parse_ies(keydata, keydatalen, &ie) < 0)
return -1;
if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
@@ -1395,6 +1602,26 @@ static int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm,
}
maxkeylen = gd->gtk_len = ie.gtk_len - 2;
+#ifdef CONFIG_OCV
+ if (wpa_sm_ocv_enabled(sm)) {
+ struct wpa_channel_info ci;
+
+ if (wpa_sm_channel_info(sm, &ci) != 0) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "Failed to get channel info to validate received OCI in EAPOL-Key group msg 1/2");
+ return -1;
+ }
+
+ if (ocv_verify_tx_params(ie.oci, ie.oci_len, &ci,
+ channel_width_to_int(ci.chanwidth),
+ ci.seg1_idx) != 0) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "%s",
+ ocv_errorstr);
+ return -1;
+ }
+ }
+#endif /* CONFIG_OCV */
+
if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
gd->gtk_len, maxkeylen,
&gd->key_rsc_len, &gd->alg))
@@ -1514,22 +1741,30 @@ static int wpa_supplicant_send_2_of_2(struct wpa_sm *sm,
{
size_t mic_len, hdrlen, rlen;
struct wpa_eapol_key *reply;
- struct wpa_eapol_key_192 *reply192;
u8 *rbuf, *key_mic;
+ size_t kde_len = 0;
- mic_len = wpa_mic_len(sm->key_mgmt);
- hdrlen = mic_len == 24 ? sizeof(*reply192) : sizeof(*reply);
+#ifdef CONFIG_OCV
+ if (wpa_sm_ocv_enabled(sm))
+ kde_len = OCV_OCI_KDE_LEN;
+#endif /* CONFIG_OCV */
+
+ mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len);
+ hdrlen = sizeof(*reply) + mic_len + 2;
rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
- hdrlen, &rlen, (void *) &reply);
+ hdrlen + kde_len, &rlen, (void *) &reply);
if (rbuf == NULL)
return -1;
- reply192 = (struct wpa_eapol_key_192 *) reply;
reply->type = (sm->proto == WPA_PROTO_RSN ||
sm->proto == WPA_PROTO_OSEN) ?
EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
key_info &= WPA_KEY_INFO_KEY_INDEX_MASK;
- key_info |= ver | WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE;
+ key_info |= ver | WPA_KEY_INFO_SECURE;
+ if (mic_len)
+ key_info |= WPA_KEY_INFO_MIC;
+ else
+ key_info |= WPA_KEY_INFO_ENCR_KEY_DATA;
WPA_PUT_BE16(reply->key_info, key_info);
if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN)
WPA_PUT_BE16(reply->key_length, 0);
@@ -1538,15 +1773,32 @@ static int wpa_supplicant_send_2_of_2(struct wpa_sm *sm,
os_memcpy(reply->replay_counter, key->replay_counter,
WPA_REPLAY_COUNTER_LEN);
- key_mic = reply192->key_mic; /* same offset for reply and reply192 */
- if (mic_len == 24)
- WPA_PUT_BE16(reply192->key_data_length, 0);
- else
- WPA_PUT_BE16(reply->key_data_length, 0);
+ key_mic = (u8 *) (reply + 1);
+ WPA_PUT_BE16(key_mic + mic_len, kde_len); /* Key Data Length */
+
+#ifdef CONFIG_OCV
+ if (wpa_sm_ocv_enabled(sm)) {
+ struct wpa_channel_info ci;
+ u8 *pos;
+
+ if (wpa_sm_channel_info(sm, &ci) != 0) {
+ wpa_printf(MSG_WARNING,
+ "Failed to get channel info for OCI element in EAPOL-Key 2/2");
+ os_free(rbuf);
+ return -1;
+ }
+
+ pos = key_mic + mic_len + 2; /* Key Data */
+ if (ocv_insert_oci_kde(&ci, &pos) < 0) {
+ os_free(rbuf);
+ return -1;
+ }
+ }
+#endif /* CONFIG_OCV */
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/2");
- return wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver,
- sm->bssid, ETH_P_EAPOL, rbuf, rlen, key_mic);
+ return wpa_eapol_key_send(sm, &sm->ptk, ver, sm->bssid, ETH_P_EAPOL,
+ rbuf, rlen, key_mic);
}
@@ -1561,7 +1813,7 @@ static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm,
struct wpa_gtk_data gd;
const u8 *key_rsc;
- if (!sm->msg_3_of_4_ok) {
+ if (!sm->msg_3_of_4_ok && !wpa_fils_is_completed(sm)) {
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
"WPA: Group Key Handshake started prior to completion of 4-way handshake");
goto failed;
@@ -1622,42 +1874,68 @@ failed:
static int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm,
- struct wpa_eapol_key_192 *key,
+ struct wpa_eapol_key *key,
u16 ver,
const u8 *buf, size_t len)
{
u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN];
int ok = 0;
- size_t mic_len = wpa_mic_len(sm->key_mgmt);
+ size_t mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len);
- os_memcpy(mic, key->key_mic, mic_len);
+ os_memcpy(mic, key + 1, mic_len);
if (sm->tptk_set) {
- os_memset(key->key_mic, 0, mic_len);
- wpa_eapol_key_mic(sm->tptk.kck, sm->tptk.kck_len, sm->key_mgmt,
- ver, buf, len, key->key_mic);
- if (os_memcmp_const(mic, key->key_mic, mic_len) != 0) {
+ os_memset(key + 1, 0, mic_len);
+ if (wpa_eapol_key_mic(sm->tptk.kck, sm->tptk.kck_len,
+ sm->key_mgmt,
+ ver, buf, len, (u8 *) (key + 1)) < 0 ||
+ os_memcmp_const(mic, key + 1, mic_len) != 0) {
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
"WPA: Invalid EAPOL-Key MIC "
"when using TPTK - ignoring TPTK");
+#ifdef TEST_FUZZ
+ wpa_printf(MSG_INFO,
+ "TEST: Ignore Key MIC failure for fuzz testing");
+ goto continue_fuzz;
+#endif /* TEST_FUZZ */
} else {
+#ifdef TEST_FUZZ
+ continue_fuzz:
+#endif /* TEST_FUZZ */
ok = 1;
sm->tptk_set = 0;
sm->ptk_set = 1;
os_memcpy(&sm->ptk, &sm->tptk, sizeof(sm->ptk));
os_memset(&sm->tptk, 0, sizeof(sm->tptk));
+ /*
+ * This assures the same TPTK in sm->tptk can never be
+ * copied twice to sm->ptk as the new PTK. In
+ * combination with the installed flag in the wpa_ptk
+ * struct, this assures the same PTK is only installed
+ * once.
+ */
+ sm->renew_snonce = 1;
}
}
if (!ok && sm->ptk_set) {
- os_memset(key->key_mic, 0, mic_len);
- wpa_eapol_key_mic(sm->ptk.kck, sm->ptk.kck_len, sm->key_mgmt,
- ver, buf, len, key->key_mic);
- if (os_memcmp_const(mic, key->key_mic, mic_len) != 0) {
+ os_memset(key + 1, 0, mic_len);
+ if (wpa_eapol_key_mic(sm->ptk.kck, sm->ptk.kck_len,
+ sm->key_mgmt,
+ ver, buf, len, (u8 *) (key + 1)) < 0 ||
+ os_memcmp_const(mic, key + 1, mic_len) != 0) {
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
"WPA: Invalid EAPOL-Key MIC - "
"dropping packet");
+#ifdef TEST_FUZZ
+ wpa_printf(MSG_INFO,
+ "TEST: Ignore Key MIC failure for fuzz testing");
+ goto continue_fuzz2;
+#endif /* TEST_FUZZ */
return -1;
}
+#ifdef TEST_FUZZ
+ continue_fuzz2:
+#endif /* TEST_FUZZ */
ok = 1;
}
@@ -1677,7 +1955,8 @@ static int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm,
/* Decrypt RSN EAPOL-Key key data (RC4 or AES-WRAP) */
static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm,
- struct wpa_eapol_key *key, u16 ver,
+ struct wpa_eapol_key *key,
+ size_t mic_len, u16 ver,
u8 *key_data, size_t *key_data_len)
{
wpa_hexdump(MSG_DEBUG, "RSN: encrypted key data",
@@ -1698,6 +1977,8 @@ static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm,
return -1;
#else /* CONFIG_NO_RC4 */
u8 ek[32];
+
+ wpa_printf(MSG_DEBUG, "WPA: Decrypt Key Data using RC4");
os_memcpy(ek, key->key_iv, 16);
os_memcpy(ek + 16, sm->ptk.kek, sm->ptk.kek_len);
if (rc4_skip(ek, 32, 256, key_data, *key_data_len)) {
@@ -1710,9 +1991,12 @@ static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm,
#endif /* CONFIG_NO_RC4 */
} else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
ver == WPA_KEY_INFO_TYPE_AES_128_CMAC ||
- sm->key_mgmt == WPA_KEY_MGMT_OSEN ||
- wpa_key_mgmt_suite_b(sm->key_mgmt)) {
+ wpa_use_aes_key_wrap(sm->key_mgmt)) {
u8 *buf;
+
+ wpa_printf(MSG_DEBUG,
+ "WPA: Decrypt Key Data using AES-UNWRAP (KEK length %u)",
+ (unsigned int) sm->ptk.kek_len);
if (*key_data_len < 8 || *key_data_len % 8) {
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
"WPA: Unsupported AES-WRAP len %u",
@@ -1726,17 +2010,28 @@ static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm,
"WPA: No memory for AES-UNWRAP buffer");
return -1;
}
+#ifdef TEST_FUZZ
+ os_memset(buf, 0x11, *key_data_len);
+#endif /* TEST_FUZZ */
if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, *key_data_len / 8,
key_data, buf)) {
+#ifdef TEST_FUZZ
+ wpa_printf(MSG_INFO,
+ "TEST: Ignore AES unwrap failure for fuzz testing");
+ goto continue_fuzz;
+#endif /* TEST_FUZZ */
bin_clear_free(buf, *key_data_len);
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
"WPA: AES unwrap failed - "
"could not decrypt EAPOL-Key key data");
return -1;
}
+#ifdef TEST_FUZZ
+ continue_fuzz:
+#endif /* TEST_FUZZ */
os_memcpy(key_data, buf, *key_data_len);
bin_clear_free(buf, *key_data_len);
- WPA_PUT_BE16(key->key_data_length, *key_data_len);
+ WPA_PUT_BE16(((u8 *) (key + 1)) + mic_len, *key_data_len);
} else {
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
"WPA: Unsupported key_info type %d", ver);
@@ -1799,6 +2094,76 @@ static void wpa_eapol_key_dump(struct wpa_sm *sm,
}
+#ifdef CONFIG_FILS
+static int wpa_supp_aead_decrypt(struct wpa_sm *sm, u8 *buf, size_t buf_len,
+ size_t *key_data_len)
+{
+ struct wpa_ptk *ptk;
+ struct ieee802_1x_hdr *hdr;
+ struct wpa_eapol_key *key;
+ u8 *pos, *tmp;
+ const u8 *aad[1];
+ size_t aad_len[1];
+
+ if (*key_data_len < AES_BLOCK_SIZE) {
+ wpa_printf(MSG_INFO, "No room for AES-SIV data in the frame");
+ return -1;
+ }
+
+ if (sm->tptk_set)
+ ptk = &sm->tptk;
+ else if (sm->ptk_set)
+ ptk = &sm->ptk;
+ else
+ return -1;
+
+ hdr = (struct ieee802_1x_hdr *) buf;
+ key = (struct wpa_eapol_key *) (hdr + 1);
+ pos = (u8 *) (key + 1);
+ pos += 2; /* Pointing at the Encrypted Key Data field */
+
+ tmp = os_malloc(*key_data_len);
+ if (!tmp)
+ return -1;
+
+ /* AES-SIV AAD from EAPOL protocol version field (inclusive) to
+ * to Key Data (exclusive). */
+ aad[0] = buf;
+ aad_len[0] = pos - buf;
+ if (aes_siv_decrypt(ptk->kek, ptk->kek_len, pos, *key_data_len,
+ 1, aad, aad_len, tmp) < 0) {
+ wpa_printf(MSG_INFO, "Invalid AES-SIV data in the frame");
+ bin_clear_free(tmp, *key_data_len);
+ return -1;
+ }
+
+ /* AEAD decryption and validation completed successfully */
+ (*key_data_len) -= AES_BLOCK_SIZE;
+ wpa_hexdump_key(MSG_DEBUG, "WPA: Decrypted Key Data",
+ tmp, *key_data_len);
+
+ /* Replace Key Data field with the decrypted version */
+ os_memcpy(pos, tmp, *key_data_len);
+ pos -= 2; /* Key Data Length field */
+ WPA_PUT_BE16(pos, *key_data_len);
+ bin_clear_free(tmp, *key_data_len);
+
+ if (sm->tptk_set) {
+ sm->tptk_set = 0;
+ sm->ptk_set = 1;
+ os_memcpy(&sm->ptk, &sm->tptk, sizeof(sm->ptk));
+ os_memset(&sm->tptk, 0, sizeof(sm->tptk));
+ }
+
+ os_memcpy(sm->rx_replay_counter, key->replay_counter,
+ WPA_REPLAY_COUNTER_LEN);
+ sm->rx_replay_counter_set = 1;
+
+ return 0;
+}
+#endif /* CONFIG_FILS */
+
+
/**
* wpa_sm_rx_eapol - Process received WPA EAPOL frames
* @sm: Pointer to WPA state machine data from wpa_sm_init()
@@ -1821,20 +2186,18 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
size_t plen, data_len, key_data_len;
const struct ieee802_1x_hdr *hdr;
struct wpa_eapol_key *key;
- struct wpa_eapol_key_192 *key192;
u16 key_info, ver;
u8 *tmp = NULL;
int ret = -1;
- struct wpa_peerkey *peerkey = NULL;
- u8 *key_data;
+ u8 *mic, *key_data;
size_t mic_len, keyhdrlen;
#ifdef CONFIG_IEEE80211R
sm->ft_completed = 0;
#endif /* CONFIG_IEEE80211R */
- mic_len = wpa_mic_len(sm->key_mgmt);
- keyhdrlen = mic_len == 24 ? sizeof(*key192) : sizeof(*key);
+ mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len);
+ keyhdrlen = sizeof(*key) + mic_len + 2;
if (len < sizeof(*hdr) + keyhdrlen) {
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
@@ -1881,17 +2244,12 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
* Make a copy of the frame since we need to modify the buffer during
* MAC validation and Key Data decryption.
*/
- tmp = os_malloc(data_len);
+ tmp = os_memdup(buf, data_len);
if (tmp == NULL)
goto out;
- os_memcpy(tmp, buf, data_len);
key = (struct wpa_eapol_key *) (tmp + sizeof(struct ieee802_1x_hdr));
- key192 = (struct wpa_eapol_key_192 *)
- (tmp + sizeof(struct ieee802_1x_hdr));
- if (mic_len == 24)
- key_data = (u8 *) (key192 + 1);
- else
- key_data = (u8 *) (key + 1);
+ mic = (u8 *) (key + 1);
+ key_data = mic + mic_len + 2;
if (key->type != EAPOL_KEY_TYPE_WPA && key->type != EAPOL_KEY_TYPE_RSN)
{
@@ -1902,11 +2260,8 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
goto out;
}
- if (mic_len == 24)
- key_data_len = WPA_GET_BE16(key192->key_data_length);
- else
- key_data_len = WPA_GET_BE16(key->key_data_length);
- wpa_eapol_key_dump(sm, key, key_data_len, key192->key_mic, mic_len);
+ key_data_len = WPA_GET_BE16(mic + mic_len);
+ wpa_eapol_key_dump(sm, key, key_data_len, mic, mic_len);
if (key_data_len > plen - keyhdrlen) {
wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Invalid EAPOL-Key "
@@ -1924,23 +2279,14 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
ver != WPA_KEY_INFO_TYPE_AES_128_CMAC &&
#endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */
ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES &&
- !wpa_key_mgmt_suite_b(sm->key_mgmt) &&
- sm->key_mgmt != WPA_KEY_MGMT_OSEN) {
+ !wpa_use_akm_defined(sm->key_mgmt)) {
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
"WPA: Unsupported EAPOL-Key descriptor version %d",
ver);
goto out;
}
- if (sm->key_mgmt == WPA_KEY_MGMT_OSEN &&
- ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) {
- wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
- "OSEN: Unsupported EAPOL-Key descriptor version %d",
- ver);
- goto out;
- }
-
- if (wpa_key_mgmt_suite_b(sm->key_mgmt) &&
+ if (wpa_use_akm_defined(sm->key_mgmt) &&
ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) {
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
"RSN: Unsupported EAPOL-Key descriptor version %d (expected AKM defined = 0)",
@@ -1951,7 +2297,8 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
#ifdef CONFIG_IEEE80211R
if (wpa_key_mgmt_ft(sm->key_mgmt)) {
/* IEEE 802.11r uses a new key_info type (AES-128-CMAC). */
- if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
+ if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC &&
+ !wpa_use_akm_defined(sm->key_mgmt)) {
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
"FT: AP did not use AES-128-CMAC");
goto out;
@@ -1961,8 +2308,7 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
#ifdef CONFIG_IEEE80211W
if (wpa_key_mgmt_sha256(sm->key_mgmt)) {
if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC &&
- sm->key_mgmt != WPA_KEY_MGMT_OSEN &&
- !wpa_key_mgmt_suite_b(sm->key_mgmt)) {
+ !wpa_use_akm_defined(sm->key_mgmt)) {
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
"WPA: AP did not use the "
"negotiated AES-128-CMAC");
@@ -1971,7 +2317,7 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
} else
#endif /* CONFIG_IEEE80211W */
if (sm->pairwise_cipher == WPA_CIPHER_CCMP &&
- !wpa_key_mgmt_suite_b(sm->key_mgmt) &&
+ !wpa_use_akm_defined(sm->key_mgmt) &&
ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
"WPA: CCMP is used, but EAPOL-Key "
@@ -1991,7 +2337,7 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
} else
goto out;
} else if (sm->pairwise_cipher == WPA_CIPHER_GCMP &&
- !wpa_key_mgmt_suite_b(sm->key_mgmt) &&
+ !wpa_use_akm_defined(sm->key_mgmt) &&
ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
"WPA: GCMP is used, but EAPOL-Key "
@@ -1999,44 +2345,7 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
goto out;
}
-#ifdef CONFIG_PEERKEY
- for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) {
- if (os_memcmp(peerkey->addr, src_addr, ETH_ALEN) == 0)
- break;
- }
-
- if (!(key_info & WPA_KEY_INFO_SMK_MESSAGE) && peerkey) {
- if (!peerkey->initiator && peerkey->replay_counter_set &&
- os_memcmp(key->replay_counter, peerkey->replay_counter,
- WPA_REPLAY_COUNTER_LEN) <= 0) {
- wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
- "RSN: EAPOL-Key Replay Counter did not "
- "increase (STK) - dropping packet");
- goto out;
- } else if (peerkey->initiator) {
- u8 _tmp[WPA_REPLAY_COUNTER_LEN];
- os_memcpy(_tmp, key->replay_counter,
- WPA_REPLAY_COUNTER_LEN);
- inc_byte_array(_tmp, WPA_REPLAY_COUNTER_LEN);
- if (os_memcmp(_tmp, peerkey->replay_counter,
- WPA_REPLAY_COUNTER_LEN) != 0) {
- wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
- "RSN: EAPOL-Key Replay "
- "Counter did not match (STK) - "
- "dropping packet");
- goto out;
- }
- }
- }
-
- if (peerkey && peerkey->initiator && (key_info & WPA_KEY_INFO_ACK)) {
- wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
- "RSN: Ack bit in key_info from STK peer");
- goto out;
- }
-#endif /* CONFIG_PEERKEY */
-
- if (!peerkey && sm->rx_replay_counter_set &&
+ if (sm->rx_replay_counter_set &&
os_memcmp(key->replay_counter, sm->rx_replay_counter,
WPA_REPLAY_COUNTER_LEN) <= 0) {
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
@@ -2045,11 +2354,13 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
goto out;
}
- if (!(key_info & (WPA_KEY_INFO_ACK | WPA_KEY_INFO_SMK_MESSAGE))
-#ifdef CONFIG_PEERKEY
- && (peerkey == NULL || !peerkey->initiator)
-#endif /* CONFIG_PEERKEY */
- ) {
+ if (key_info & WPA_KEY_INFO_SMK_MESSAGE) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "WPA: Unsupported SMK bit in key_info");
+ goto out;
+ }
+
+ if (!(key_info & WPA_KEY_INFO_ACK)) {
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
"WPA: No Ack bit in key_info");
goto out;
@@ -2061,19 +2372,19 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
goto out;
}
- if ((key_info & WPA_KEY_INFO_MIC) && !peerkey &&
- wpa_supplicant_verify_eapol_key_mic(sm, key192, ver, tmp, data_len))
+ if ((key_info & WPA_KEY_INFO_MIC) &&
+ wpa_supplicant_verify_eapol_key_mic(sm, key, ver, tmp, data_len))
goto out;
-#ifdef CONFIG_PEERKEY
- if ((key_info & WPA_KEY_INFO_MIC) && peerkey &&
- peerkey_verify_eapol_key_mic(sm, peerkey, key192, ver, tmp,
- data_len))
- goto out;
-#endif /* CONFIG_PEERKEY */
+#ifdef CONFIG_FILS
+ if (!mic_len && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
+ if (wpa_supp_aead_decrypt(sm, tmp, data_len, &key_data_len))
+ goto out;
+ }
+#endif /* CONFIG_FILS */
if ((sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) &&
- (key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
+ (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) && mic_len) {
/*
* Only decrypt the Key Data field if the frame's authenticity
* was verified. When using AES-SIV (FILS), the MIC flag is not
@@ -2085,7 +2396,8 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
"WPA: Ignore EAPOL-Key with encrypted but unauthenticated data");
goto out;
}
- if (wpa_supplicant_decrypt_key_data(sm, key, ver, key_data,
+ if (wpa_supplicant_decrypt_key_data(sm, key, mic_len,
+ ver, key_data,
&key_data_len))
goto out;
}
@@ -2097,11 +2409,8 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
"non-zero key index");
goto out;
}
- if (peerkey) {
- /* PeerKey 4-Way Handshake */
- peerkey_rx_eapol_4way(sm, peerkey, key, key_info, ver,
- key_data, key_data_len);
- } else if (key_info & WPA_KEY_INFO_MIC) {
+ if (key_info & (WPA_KEY_INFO_MIC |
+ WPA_KEY_INFO_ENCR_KEY_DATA)) {
/* 3/4 4-Way Handshake */
wpa_supplicant_process_3_of_4(sm, key, ver, key_data,
key_data_len);
@@ -2111,19 +2420,16 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
ver, key_data,
key_data_len);
}
- } else if (key_info & WPA_KEY_INFO_SMK_MESSAGE) {
- /* PeerKey SMK Handshake */
- peerkey_rx_eapol_smk(sm, src_addr, key, key_data_len, key_info,
- ver);
} else {
- if (key_info & WPA_KEY_INFO_MIC) {
+ if ((mic_len && (key_info & WPA_KEY_INFO_MIC)) ||
+ (!mic_len && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA))) {
/* 1/2 Group Key Handshake */
wpa_supplicant_process_1_of_2(sm, src_addr, key,
key_data, key_data_len,
ver);
} else {
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
- "WPA: EAPOL-Key (Group) without Mic bit - "
+ "WPA: EAPOL-Key (Group) without Mic/Encr bit - "
"dropped");
}
}
@@ -2298,6 +2604,7 @@ static void wpa_sm_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry,
}
if (deauth) {
+ sm->pmk_len = 0;
os_memset(sm->pmk, 0, sizeof(sm->pmk));
wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
}
@@ -2355,13 +2662,24 @@ void wpa_sm_deinit(struct wpa_sm *sm)
os_free(sm->ap_rsn_ie);
wpa_sm_drop_sa(sm);
os_free(sm->ctx);
- peerkey_deinit(sm);
#ifdef CONFIG_IEEE80211R
os_free(sm->assoc_resp_ies);
#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_TESTING_OPTIONS
wpabuf_free(sm->test_assoc_ie);
#endif /* CONFIG_TESTING_OPTIONS */
+#ifdef CONFIG_FILS_SK_PFS
+ crypto_ecdh_deinit(sm->fils_ecdh);
+#endif /* CONFIG_FILS_SK_PFS */
+#ifdef CONFIG_FILS
+ wpabuf_free(sm->fils_ft_ies);
+#endif /* CONFIG_FILS */
+#ifdef CONFIG_OWE
+ crypto_ecdh_deinit(sm->owe_ecdh);
+#endif /* CONFIG_OWE */
+#ifdef CONFIG_DPP2
+ wpabuf_clear_free(sm->dpp_z);
+#endif /* CONFIG_DPP2 */
os_free(sm);
}
@@ -2403,8 +2721,21 @@ void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid)
wpa_ft_prepare_auth_request(sm, NULL);
clear_keys = 0;
+ sm->ft_protocol = 1;
+ } else {
+ sm->ft_protocol = 0;
}
#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_FILS
+ if (sm->fils_completed) {
+ /*
+ * Clear portValid to kick EAPOL state machine to re-enter
+ * AUTHENTICATED state to get the EAPOL port Authorized.
+ */
+ wpa_supplicant_key_neg_complete(sm, sm->bssid, 1);
+ clear_keys = 0;
+ }
+#endif /* CONFIG_FILS */
if (clear_keys) {
/*
@@ -2445,7 +2776,6 @@ void wpa_sm_notify_disassoc(struct wpa_sm *sm)
{
eloop_cancel_timeout(wpa_sm_start_preauth, sm, NULL);
eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL);
- peerkey_deinit(sm);
rsn_preauth_deinit(sm);
pmksa_cache_clear_current(sm);
if (wpa_sm_get_state(sm) == WPA_4WAY_HANDSHAKE)
@@ -2453,14 +2783,19 @@ void wpa_sm_notify_disassoc(struct wpa_sm *sm)
#ifdef CONFIG_TDLS
wpa_tdls_disassoc(sm);
#endif /* CONFIG_TDLS */
+#ifdef CONFIG_FILS
+ sm->fils_completed = 0;
+#endif /* CONFIG_FILS */
#ifdef CONFIG_IEEE80211R
sm->ft_reassoc_completed = 0;
+ sm->ft_protocol = 0;
#endif /* CONFIG_IEEE80211R */
/* Keys are not needed in the WPA state machine anymore */
wpa_sm_drop_sa(sm);
sm->msg_3_of_4_ok = 0;
+ os_memset(sm->bssid, 0, ETH_ALEN);
}
@@ -2480,6 +2815,8 @@ void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len,
if (sm == NULL)
return;
+ wpa_hexdump_key(MSG_DEBUG, "WPA: Set PMK based on external data",
+ pmk, pmk_len);
sm->pmk_len = pmk_len;
os_memcpy(sm->pmk, pmk, pmk_len);
@@ -2492,7 +2829,7 @@ void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len,
if (bssid) {
pmksa_cache_add(sm->pmksa, pmk, pmk_len, pmkid, NULL, 0,
bssid, sm->own_addr,
- sm->network_ctx, sm->key_mgmt);
+ sm->network_ctx, sm->key_mgmt, NULL);
}
}
@@ -2510,11 +2847,15 @@ void wpa_sm_set_pmk_from_pmksa(struct wpa_sm *sm)
return;
if (sm->cur_pmksa) {
+ wpa_hexdump_key(MSG_DEBUG,
+ "WPA: Set PMK based on current PMKSA",
+ sm->cur_pmksa->pmk, sm->cur_pmksa->pmk_len);
sm->pmk_len = sm->cur_pmksa->pmk_len;
os_memcpy(sm->pmk, sm->cur_pmksa->pmk, sm->pmk_len);
} else {
- sm->pmk_len = PMK_LEN;
- os_memset(sm->pmk, 0, PMK_LEN);
+ wpa_printf(MSG_DEBUG, "WPA: No current PMKSA - clear PMK");
+ sm->pmk_len = 0;
+ os_memset(sm->pmk, 0, PMK_LEN_MAX);
}
}
@@ -2562,7 +2903,6 @@ void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config)
if (config) {
sm->network_ctx = config->network_ctx;
- sm->peerkey_enabled = config->peerkey_enabled;
sm->allowed_pairwise_cipher = config->allowed_pairwise_cipher;
sm->proactive_key_caching = config->proactive_key_caching;
sm->eap_workaround = config->eap_workaround;
@@ -2575,9 +2915,17 @@ void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config)
sm->wpa_ptk_rekey = config->wpa_ptk_rekey;
sm->p2p = config->p2p;
sm->wpa_rsc_relaxation = config->wpa_rsc_relaxation;
+#ifdef CONFIG_FILS
+ if (config->fils_cache_id) {
+ sm->fils_cache_id_set = 1;
+ os_memcpy(sm->fils_cache_id, config->fils_cache_id,
+ FILS_CACHE_ID_LEN);
+ } else {
+ sm->fils_cache_id_set = 0;
+ }
+#endif /* CONFIG_FILS */
} else {
sm->network_ctx = NULL;
- sm->peerkey_enabled = 0;
sm->allowed_pairwise_cipher = 0;
sm->proactive_key_caching = 0;
sm->eap_workaround = 0;
@@ -2687,6 +3035,9 @@ int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param,
case WPA_PARAM_MFP:
sm->mfp = value;
break;
+ case WPA_PARAM_OCV:
+ sm->ocv = value;
+ break;
default:
break;
}
@@ -2730,9 +3081,12 @@ int wpa_sm_get_status(struct wpa_sm *sm, char *buf, size_t buflen,
>= 0 &&
rsn.capabilities & (WPA_CAPABILITY_MFPR |
WPA_CAPABILITY_MFPC)) {
- ret = os_snprintf(pos, end - pos, "pmf=%d\n",
+ ret = os_snprintf(pos, end - pos, "pmf=%d\n"
+ "mgmt_group_cipher=%s\n",
(rsn.capabilities &
- WPA_CAPABILITY_MFPR) ? 2 : 1);
+ WPA_CAPABILITY_MFPR) ? 2 : 1,
+ wpa_cipher_txt(
+ sm->mgmt_group_cipher));
if (os_snprintf_error(end - pos, ret))
return pos - buf;
pos += ret;
@@ -2758,6 +3112,19 @@ int wpa_sm_pmf_enabled(struct wpa_sm *sm)
}
+int wpa_sm_ocv_enabled(struct wpa_sm *sm)
+{
+ struct wpa_ie_data rsn;
+
+ if (!sm->ocv || !sm->ap_rsn_ie)
+ return 0;
+
+ return wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len,
+ &rsn) >= 0 &&
+ (rsn.capabilities & WPA_CAPABILITY_OCVC);
+}
+
+
/**
* wpa_sm_set_assoc_wpa_ie_default - Generate own WPA/RSN IE from configuration
* @sm: Pointer to WPA state machine data from wpa_sm_init()
@@ -2798,12 +3165,15 @@ int wpa_sm_set_assoc_wpa_ie_default(struct wpa_sm *sm, u8 *wpa_ie,
* the correct version of the IE even if PMKSA caching is
* aborted (which would remove PMKID from IE generation).
*/
- sm->assoc_wpa_ie = os_malloc(*wpa_ie_len);
+ sm->assoc_wpa_ie = os_memdup(wpa_ie, *wpa_ie_len);
if (sm->assoc_wpa_ie == NULL)
return -1;
- os_memcpy(sm->assoc_wpa_ie, wpa_ie, *wpa_ie_len);
sm->assoc_wpa_ie_len = *wpa_ie_len;
+ } else {
+ wpa_hexdump(MSG_DEBUG,
+ "WPA: Leave previously set WPA IE default",
+ sm->assoc_wpa_ie, sm->assoc_wpa_ie_len);
}
return 0;
@@ -2834,11 +3204,10 @@ int wpa_sm_set_assoc_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
sm->assoc_wpa_ie_len = 0;
} else {
wpa_hexdump(MSG_DEBUG, "WPA: set own WPA/RSN IE", ie, len);
- sm->assoc_wpa_ie = os_malloc(len);
+ sm->assoc_wpa_ie = os_memdup(ie, len);
if (sm->assoc_wpa_ie == NULL)
return -1;
- os_memcpy(sm->assoc_wpa_ie, ie, len);
sm->assoc_wpa_ie_len = len;
}
@@ -2869,11 +3238,10 @@ int wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
sm->ap_wpa_ie_len = 0;
} else {
wpa_hexdump(MSG_DEBUG, "WPA: set AP WPA IE", ie, len);
- sm->ap_wpa_ie = os_malloc(len);
+ sm->ap_wpa_ie = os_memdup(ie, len);
if (sm->ap_wpa_ie == NULL)
return -1;
- os_memcpy(sm->ap_wpa_ie, ie, len);
sm->ap_wpa_ie_len = len;
}
@@ -2904,11 +3272,10 @@ int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
sm->ap_rsn_ie_len = 0;
} else {
wpa_hexdump(MSG_DEBUG, "WPA: set AP RSN IE", ie, len);
- sm->ap_rsn_ie = os_malloc(len);
+ sm->ap_rsn_ie = os_memdup(ie, len);
if (sm->ap_rsn_ie == NULL)
return -1;
- os_memcpy(sm->ap_rsn_ie, ie, len);
sm->ap_rsn_ie_len = len;
}
@@ -2947,11 +3314,43 @@ int wpa_sm_pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len)
}
+struct rsn_pmksa_cache_entry * wpa_sm_pmksa_cache_head(struct wpa_sm *sm)
+{
+ return pmksa_cache_head(sm->pmksa);
+}
+
+
+struct rsn_pmksa_cache_entry *
+wpa_sm_pmksa_cache_add_entry(struct wpa_sm *sm,
+ struct rsn_pmksa_cache_entry * entry)
+{
+ return pmksa_cache_add_entry(sm->pmksa, entry);
+}
+
+
+void wpa_sm_pmksa_cache_add(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len,
+ const u8 *pmkid, const u8 *bssid,
+ const u8 *fils_cache_id)
+{
+ sm->cur_pmksa = pmksa_cache_add(sm->pmksa, pmk, pmk_len, pmkid, NULL, 0,
+ bssid, sm->own_addr, sm->network_ctx,
+ sm->key_mgmt, fils_cache_id);
+}
+
+
+int wpa_sm_pmksa_exists(struct wpa_sm *sm, const u8 *bssid,
+ const void *network_ctx)
+{
+ return pmksa_cache_get(sm->pmksa, bssid, NULL, network_ctx, 0) != NULL;
+}
+
+
void wpa_sm_drop_sa(struct wpa_sm *sm)
{
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Clear old PMK and PTK");
sm->ptk_set = 0;
sm->tptk_set = 0;
+ sm->pmk_len = 0;
os_memset(sm->pmk, 0, sizeof(sm->pmk));
os_memset(&sm->ptk, 0, sizeof(sm->ptk));
os_memset(&sm->tptk, 0, sizeof(sm->tptk));
@@ -2963,8 +3362,11 @@ void wpa_sm_drop_sa(struct wpa_sm *sm)
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_IEEE80211R
os_memset(sm->xxkey, 0, sizeof(sm->xxkey));
+ sm->xxkey_len = 0;
os_memset(sm->pmk_r0, 0, sizeof(sm->pmk_r0));
+ sm->pmk_r0_len = 0;
os_memset(sm->pmk_r1, 0, sizeof(sm->pmk_r1));
+ sm->pmk_r1_len = 0;
#endif /* CONFIG_IEEE80211R */
}
@@ -3049,27 +3451,6 @@ int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf)
#endif /* CONFIG_WNM */
-#ifdef CONFIG_PEERKEY
-int wpa_sm_rx_eapol_peerkey(struct wpa_sm *sm, const u8 *src_addr,
- const u8 *buf, size_t len)
-{
- struct wpa_peerkey *peerkey;
-
- for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) {
- if (os_memcmp(peerkey->addr, src_addr, ETH_ALEN) == 0)
- break;
- }
-
- if (!peerkey)
- return 0;
-
- wpa_sm_rx_eapol(sm, src_addr, buf, len);
-
- return 1;
-}
-#endif /* CONFIG_PEERKEY */
-
-
#ifdef CONFIG_P2P
int wpa_sm_get_p2p_ip_addr(struct wpa_sm *sm, u8 *buf)
@@ -3114,9 +3495,1202 @@ void wpa_sm_set_ptk_kck_kek(struct wpa_sm *sm,
#ifdef CONFIG_TESTING_OPTIONS
+
void wpa_sm_set_test_assoc_ie(struct wpa_sm *sm, struct wpabuf *buf)
{
wpabuf_free(sm->test_assoc_ie);
sm->test_assoc_ie = buf;
}
+
+
+const u8 * wpa_sm_get_anonce(struct wpa_sm *sm)
+{
+ return sm->anonce;
+}
+
#endif /* CONFIG_TESTING_OPTIONS */
+
+
+unsigned int wpa_sm_get_key_mgmt(struct wpa_sm *sm)
+{
+ return sm->key_mgmt;
+}
+
+
+#ifdef CONFIG_FILS
+
+struct wpabuf * fils_build_auth(struct wpa_sm *sm, int dh_group, const u8 *md)
+{
+ struct wpabuf *buf = NULL;
+ struct wpabuf *erp_msg;
+ struct wpabuf *pub = NULL;
+
+ erp_msg = eapol_sm_build_erp_reauth_start(sm->eapol);
+ if (!erp_msg && !sm->cur_pmksa) {
+ wpa_printf(MSG_DEBUG,
+ "FILS: Neither ERP EAP-Initiate/Re-auth nor PMKSA cache entry is available - skip FILS");
+ goto fail;
+ }
+
+ wpa_printf(MSG_DEBUG, "FILS: Try to use FILS (erp=%d pmksa_cache=%d)",
+ erp_msg != NULL, sm->cur_pmksa != NULL);
+
+ sm->fils_completed = 0;
+
+ if (!sm->assoc_wpa_ie) {
+ wpa_printf(MSG_INFO, "FILS: No own RSN IE set for FILS");
+ goto fail;
+ }
+
+ if (random_get_bytes(sm->fils_nonce, FILS_NONCE_LEN) < 0 ||
+ random_get_bytes(sm->fils_session, FILS_SESSION_LEN) < 0)
+ goto fail;
+
+ wpa_hexdump(MSG_DEBUG, "FILS: Generated FILS Nonce",
+ sm->fils_nonce, FILS_NONCE_LEN);
+ wpa_hexdump(MSG_DEBUG, "FILS: Generated FILS Session",
+ sm->fils_session, FILS_SESSION_LEN);
+
+#ifdef CONFIG_FILS_SK_PFS
+ sm->fils_dh_group = dh_group;
+ if (dh_group) {
+ crypto_ecdh_deinit(sm->fils_ecdh);
+ sm->fils_ecdh = crypto_ecdh_init(dh_group);
+ if (!sm->fils_ecdh) {
+ wpa_printf(MSG_INFO,
+ "FILS: Could not initialize ECDH with group %d",
+ dh_group);
+ goto fail;
+ }
+ pub = crypto_ecdh_get_pubkey(sm->fils_ecdh, 1);
+ if (!pub)
+ goto fail;
+ wpa_hexdump_buf(MSG_DEBUG, "FILS: Element (DH public key)",
+ pub);
+ sm->fils_dh_elem_len = wpabuf_len(pub);
+ }
+#endif /* CONFIG_FILS_SK_PFS */
+
+ buf = wpabuf_alloc(1000 + sm->assoc_wpa_ie_len +
+ (pub ? wpabuf_len(pub) : 0));
+ if (!buf)
+ goto fail;
+
+ /* Fields following the Authentication algorithm number field */
+
+ /* Authentication Transaction seq# */
+ wpabuf_put_le16(buf, 1);
+
+ /* Status Code */
+ wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
+
+ /* TODO: FILS PK */
+#ifdef CONFIG_FILS_SK_PFS
+ if (dh_group) {
+ /* Finite Cyclic Group */
+ wpabuf_put_le16(buf, dh_group);
+ /* Element */
+ wpabuf_put_buf(buf, pub);
+ }
+#endif /* CONFIG_FILS_SK_PFS */
+
+ /* RSNE */
+ wpa_hexdump(MSG_DEBUG, "FILS: RSNE in FILS Authentication frame",
+ sm->assoc_wpa_ie, sm->assoc_wpa_ie_len);
+ wpabuf_put_data(buf, sm->assoc_wpa_ie, sm->assoc_wpa_ie_len);
+
+ if (md) {
+ /* MDE when using FILS for FT initial association */
+ struct rsn_mdie *mdie;
+
+ wpabuf_put_u8(buf, WLAN_EID_MOBILITY_DOMAIN);
+ wpabuf_put_u8(buf, sizeof(*mdie));
+ mdie = wpabuf_put(buf, sizeof(*mdie));
+ os_memcpy(mdie->mobility_domain, md, MOBILITY_DOMAIN_ID_LEN);
+ mdie->ft_capab = 0;
+ }
+
+ /* FILS Nonce */
+ wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */
+ wpabuf_put_u8(buf, 1 + FILS_NONCE_LEN); /* Length */
+ /* Element ID Extension */
+ wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_NONCE);
+ wpabuf_put_data(buf, sm->fils_nonce, FILS_NONCE_LEN);
+
+ /* FILS Session */
+ wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */
+ wpabuf_put_u8(buf, 1 + FILS_SESSION_LEN); /* Length */
+ /* Element ID Extension */
+ wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_SESSION);
+ wpabuf_put_data(buf, sm->fils_session, FILS_SESSION_LEN);
+
+ /* FILS Wrapped Data */
+ sm->fils_erp_pmkid_set = 0;
+ if (erp_msg) {
+ wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */
+ wpabuf_put_u8(buf, 1 + wpabuf_len(erp_msg)); /* Length */
+ /* Element ID Extension */
+ wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_WRAPPED_DATA);
+ wpabuf_put_buf(buf, erp_msg);
+ /* Calculate pending PMKID here so that we do not need to
+ * maintain a copy of the EAP-Initiate/Reauth message. */
+ if (fils_pmkid_erp(sm->key_mgmt, wpabuf_head(erp_msg),
+ wpabuf_len(erp_msg),
+ sm->fils_erp_pmkid) == 0)
+ sm->fils_erp_pmkid_set = 1;
+ }
+
+ wpa_hexdump_buf(MSG_DEBUG, "RSN: FILS fields for Authentication frame",
+ buf);
+
+fail:
+ wpabuf_free(erp_msg);
+ wpabuf_free(pub);
+ return buf;
+}
+
+
+int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
+ size_t len)
+{
+ const u8 *pos, *end;
+ struct ieee802_11_elems elems;
+ struct wpa_ie_data rsn;
+ int pmkid_match = 0;
+ u8 ick[FILS_ICK_MAX_LEN];
+ size_t ick_len;
+ int res;
+ struct wpabuf *dh_ss = NULL;
+ const u8 *g_sta = NULL;
+ size_t g_sta_len = 0;
+ const u8 *g_ap = NULL;
+ size_t g_ap_len = 0;
+ struct wpabuf *pub = NULL;
+
+ os_memcpy(sm->bssid, bssid, ETH_ALEN);
+
+ wpa_hexdump(MSG_DEBUG, "FILS: Authentication frame fields",
+ data, len);
+ pos = data;
+ end = data + len;
+
+ /* TODO: FILS PK */
+#ifdef CONFIG_FILS_SK_PFS
+ if (sm->fils_dh_group) {
+ u16 group;
+
+ /* Using FILS PFS */
+
+ /* Finite Cyclic Group */
+ if (end - pos < 2) {
+ wpa_printf(MSG_DEBUG,
+ "FILS: No room for Finite Cyclic Group");
+ goto fail;
+ }
+ group = WPA_GET_LE16(pos);
+ pos += 2;
+ if (group != sm->fils_dh_group) {
+ wpa_printf(MSG_DEBUG,
+ "FILS: Unexpected change in Finite Cyclic Group: %u (expected %u)",
+ group, sm->fils_dh_group);
+ goto fail;
+ }
+
+ /* Element */
+ if ((size_t) (end - pos) < sm->fils_dh_elem_len) {
+ wpa_printf(MSG_DEBUG, "FILS: No room for Element");
+ goto fail;
+ }
+
+ if (!sm->fils_ecdh) {
+ wpa_printf(MSG_DEBUG, "FILS: No ECDH state available");
+ goto fail;
+ }
+ dh_ss = crypto_ecdh_set_peerkey(sm->fils_ecdh, 1, pos,
+ sm->fils_dh_elem_len);
+ if (!dh_ss) {
+ wpa_printf(MSG_DEBUG, "FILS: ECDH operation failed");
+ goto fail;
+ }
+ wpa_hexdump_buf_key(MSG_DEBUG, "FILS: DH_SS", dh_ss);
+ g_ap = pos;
+ g_ap_len = sm->fils_dh_elem_len;
+ pos += sm->fils_dh_elem_len;
+ }
+#endif /* CONFIG_FILS_SK_PFS */
+
+ wpa_hexdump(MSG_DEBUG, "FILS: Remaining IEs", pos, end - pos);
+ if (ieee802_11_parse_elems(pos, end - pos, &elems, 1) == ParseFailed) {
+ wpa_printf(MSG_DEBUG, "FILS: Could not parse elements");
+ goto fail;
+ }
+
+ /* RSNE */
+ wpa_hexdump(MSG_DEBUG, "FILS: RSN element", elems.rsn_ie,
+ elems.rsn_ie_len);
+ if (!elems.rsn_ie ||
+ wpa_parse_wpa_ie_rsn(elems.rsn_ie - 2, elems.rsn_ie_len + 2,
+ &rsn) < 0) {
+ wpa_printf(MSG_DEBUG, "FILS: No RSN element");
+ goto fail;
+ }
+
+ if (!elems.fils_nonce) {
+ wpa_printf(MSG_DEBUG, "FILS: No FILS Nonce field");
+ goto fail;
+ }
+ os_memcpy(sm->fils_anonce, elems.fils_nonce, FILS_NONCE_LEN);
+ wpa_hexdump(MSG_DEBUG, "FILS: ANonce", sm->fils_anonce, FILS_NONCE_LEN);
+
+#ifdef CONFIG_IEEE80211R
+ if (wpa_key_mgmt_ft(sm->key_mgmt)) {
+ struct wpa_ft_ies parse;
+
+ if (!elems.mdie || !elems.ftie) {
+ wpa_printf(MSG_DEBUG, "FILS+FT: No MDE or FTE");
+ goto fail;
+ }
+
+ if (wpa_ft_parse_ies(pos, end - pos, &parse,
+ wpa_key_mgmt_sha384(sm->key_mgmt)) < 0) {
+ wpa_printf(MSG_DEBUG, "FILS+FT: Failed to parse IEs");
+ goto fail;
+ }
+
+ if (!parse.r0kh_id) {
+ wpa_printf(MSG_DEBUG,
+ "FILS+FT: No R0KH-ID subelem in FTE");
+ goto fail;
+ }
+ os_memcpy(sm->r0kh_id, parse.r0kh_id, parse.r0kh_id_len);
+ sm->r0kh_id_len = parse.r0kh_id_len;
+ wpa_hexdump_ascii(MSG_DEBUG, "FILS+FT: R0KH-ID",
+ sm->r0kh_id, sm->r0kh_id_len);
+
+ if (!parse.r1kh_id) {
+ wpa_printf(MSG_DEBUG,
+ "FILS+FT: No R1KH-ID subelem in FTE");
+ goto fail;
+ }
+ os_memcpy(sm->r1kh_id, parse.r1kh_id, FT_R1KH_ID_LEN);
+ wpa_hexdump(MSG_DEBUG, "FILS+FT: R1KH-ID",
+ sm->r1kh_id, FT_R1KH_ID_LEN);
+
+ /* TODO: Check MDE and FTE payload */
+
+ wpabuf_free(sm->fils_ft_ies);
+ sm->fils_ft_ies = wpabuf_alloc(2 + elems.mdie_len +
+ 2 + elems.ftie_len);
+ if (!sm->fils_ft_ies)
+ goto fail;
+ wpabuf_put_data(sm->fils_ft_ies, elems.mdie - 2,
+ 2 + elems.mdie_len);
+ wpabuf_put_data(sm->fils_ft_ies, elems.ftie - 2,
+ 2 + elems.ftie_len);
+ } else {
+ wpabuf_free(sm->fils_ft_ies);
+ sm->fils_ft_ies = NULL;
+ }
+#endif /* CONFIG_IEEE80211R */
+
+ /* PMKID List */
+ if (rsn.pmkid && rsn.num_pmkid > 0) {
+ wpa_hexdump(MSG_DEBUG, "FILS: PMKID List",
+ rsn.pmkid, rsn.num_pmkid * PMKID_LEN);
+
+ if (rsn.num_pmkid != 1) {
+ wpa_printf(MSG_DEBUG, "FILS: Invalid PMKID selection");
+ goto fail;
+ }
+ wpa_hexdump(MSG_DEBUG, "FILS: PMKID", rsn.pmkid, PMKID_LEN);
+ if (os_memcmp(sm->cur_pmksa->pmkid, rsn.pmkid, PMKID_LEN) != 0)
+ {
+ wpa_printf(MSG_DEBUG, "FILS: PMKID mismatch");
+ wpa_hexdump(MSG_DEBUG, "FILS: Expected PMKID",
+ sm->cur_pmksa->pmkid, PMKID_LEN);
+ goto fail;
+ }
+ wpa_printf(MSG_DEBUG,
+ "FILS: Matching PMKID - continue using PMKSA caching");
+ pmkid_match = 1;
+ }
+ if (!pmkid_match && sm->cur_pmksa) {
+ wpa_printf(MSG_DEBUG,
+ "FILS: No PMKID match - cannot use cached PMKSA entry");
+ sm->cur_pmksa = NULL;
+ }
+
+ /* FILS Session */
+ if (!elems.fils_session) {
+ wpa_printf(MSG_DEBUG, "FILS: No FILS Session element");
+ goto fail;
+ }
+ wpa_hexdump(MSG_DEBUG, "FILS: FILS Session", elems.fils_session,
+ FILS_SESSION_LEN);
+ if (os_memcmp(sm->fils_session, elems.fils_session, FILS_SESSION_LEN)
+ != 0) {
+ wpa_printf(MSG_DEBUG, "FILS: Session mismatch");
+ wpa_hexdump(MSG_DEBUG, "FILS: Expected FILS Session",
+ sm->fils_session, FILS_SESSION_LEN);
+ goto fail;
+ }
+
+ /* FILS Wrapped Data */
+ if (!sm->cur_pmksa && elems.fils_wrapped_data) {
+ u8 rmsk[ERP_MAX_KEY_LEN];
+ size_t rmsk_len;
+
+ wpa_hexdump(MSG_DEBUG, "FILS: Wrapped Data",
+ elems.fils_wrapped_data,
+ elems.fils_wrapped_data_len);
+ eapol_sm_process_erp_finish(sm->eapol, elems.fils_wrapped_data,
+ elems.fils_wrapped_data_len);
+ if (eapol_sm_failed(sm->eapol))
+ goto fail;
+
+ rmsk_len = ERP_MAX_KEY_LEN;
+ res = eapol_sm_get_key(sm->eapol, rmsk, rmsk_len);
+ if (res == PMK_LEN) {
+ rmsk_len = PMK_LEN;
+ res = eapol_sm_get_key(sm->eapol, rmsk, rmsk_len);
+ }
+ if (res)
+ goto fail;
+
+ res = fils_rmsk_to_pmk(sm->key_mgmt, rmsk, rmsk_len,
+ sm->fils_nonce, sm->fils_anonce,
+ dh_ss ? wpabuf_head(dh_ss) : NULL,
+ dh_ss ? wpabuf_len(dh_ss) : 0,
+ sm->pmk, &sm->pmk_len);
+ os_memset(rmsk, 0, sizeof(rmsk));
+
+ /* Don't use DHss in PTK derivation if PMKSA caching is not
+ * used. */
+ wpabuf_clear_free(dh_ss);
+ dh_ss = NULL;
+
+ if (res)
+ goto fail;
+
+ if (!sm->fils_erp_pmkid_set) {
+ wpa_printf(MSG_DEBUG, "FILS: PMKID not available");
+ goto fail;
+ }
+ wpa_hexdump(MSG_DEBUG, "FILS: PMKID", sm->fils_erp_pmkid,
+ PMKID_LEN);
+ wpa_printf(MSG_DEBUG, "FILS: ERP processing succeeded - add PMKSA cache entry for the result");
+ sm->cur_pmksa = pmksa_cache_add(sm->pmksa, sm->pmk, sm->pmk_len,
+ sm->fils_erp_pmkid, NULL, 0,
+ sm->bssid, sm->own_addr,
+ sm->network_ctx, sm->key_mgmt,
+ NULL);
+ }
+
+ if (!sm->cur_pmksa) {
+ wpa_printf(MSG_DEBUG,
+ "FILS: No remaining options to continue FILS authentication");
+ goto fail;
+ }
+
+ if (fils_pmk_to_ptk(sm->pmk, sm->pmk_len, sm->own_addr, sm->bssid,
+ sm->fils_nonce, sm->fils_anonce,
+ dh_ss ? wpabuf_head(dh_ss) : NULL,
+ dh_ss ? wpabuf_len(dh_ss) : 0,
+ &sm->ptk, ick, &ick_len,
+ sm->key_mgmt, sm->pairwise_cipher,
+ sm->fils_ft, &sm->fils_ft_len) < 0) {
+ wpa_printf(MSG_DEBUG, "FILS: Failed to derive PTK");
+ goto fail;
+ }
+
+ wpabuf_clear_free(dh_ss);
+ dh_ss = NULL;
+
+ sm->ptk_set = 1;
+ sm->tptk_set = 0;
+ os_memset(&sm->tptk, 0, sizeof(sm->tptk));
+
+#ifdef CONFIG_FILS_SK_PFS
+ if (sm->fils_dh_group) {
+ if (!sm->fils_ecdh) {
+ wpa_printf(MSG_INFO, "FILS: ECDH not initialized");
+ goto fail;
+ }
+ pub = crypto_ecdh_get_pubkey(sm->fils_ecdh, 1);
+ if (!pub)
+ goto fail;
+ wpa_hexdump_buf(MSG_DEBUG, "FILS: gSTA", pub);
+ g_sta = wpabuf_head(pub);
+ g_sta_len = wpabuf_len(pub);
+ if (!g_ap) {
+ wpa_printf(MSG_INFO, "FILS: gAP not available");
+ goto fail;
+ }
+ wpa_hexdump(MSG_DEBUG, "FILS: gAP", g_ap, g_ap_len);
+ }
+#endif /* CONFIG_FILS_SK_PFS */
+
+ res = fils_key_auth_sk(ick, ick_len, sm->fils_nonce,
+ sm->fils_anonce, sm->own_addr, sm->bssid,
+ g_sta, g_sta_len, g_ap, g_ap_len,
+ sm->key_mgmt, sm->fils_key_auth_sta,
+ sm->fils_key_auth_ap,
+ &sm->fils_key_auth_len);
+ wpabuf_free(pub);
+ os_memset(ick, 0, sizeof(ick));
+ return res;
+fail:
+ wpabuf_free(pub);
+ wpabuf_clear_free(dh_ss);
+ return -1;
+}
+
+
+#ifdef CONFIG_IEEE80211R
+static int fils_ft_build_assoc_req_rsne(struct wpa_sm *sm, struct wpabuf *buf)
+{
+ struct rsn_ie_hdr *rsnie;
+ u16 capab;
+ u8 *pos;
+ int use_sha384 = wpa_key_mgmt_sha384(sm->key_mgmt);
+
+ /* RSNIE[PMKR0Name/PMKR1Name] */
+ rsnie = wpabuf_put(buf, sizeof(*rsnie));
+ rsnie->elem_id = WLAN_EID_RSN;
+ WPA_PUT_LE16(rsnie->version, RSN_VERSION);
+
+ /* Group Suite Selector */
+ if (!wpa_cipher_valid_group(sm->group_cipher)) {
+ wpa_printf(MSG_WARNING, "FT: Invalid group cipher (%d)",
+ sm->group_cipher);
+ return -1;
+ }
+ pos = wpabuf_put(buf, RSN_SELECTOR_LEN);
+ RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN,
+ sm->group_cipher));
+
+ /* Pairwise Suite Count */
+ wpabuf_put_le16(buf, 1);
+
+ /* Pairwise Suite List */
+ if (!wpa_cipher_valid_pairwise(sm->pairwise_cipher)) {
+ wpa_printf(MSG_WARNING, "FT: Invalid pairwise cipher (%d)",
+ sm->pairwise_cipher);
+ return -1;
+ }
+ pos = wpabuf_put(buf, RSN_SELECTOR_LEN);
+ RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN,
+ sm->pairwise_cipher));
+
+ /* Authenticated Key Management Suite Count */
+ wpabuf_put_le16(buf, 1);
+
+ /* Authenticated Key Management Suite List */
+ pos = wpabuf_put(buf, RSN_SELECTOR_LEN);
+ if (sm->key_mgmt == WPA_KEY_MGMT_FT_FILS_SHA256)
+ RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA256);
+ else if (sm->key_mgmt == WPA_KEY_MGMT_FT_FILS_SHA384)
+ RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA384);
+ else {
+ wpa_printf(MSG_WARNING,
+ "FILS+FT: Invalid key management type (%d)",
+ sm->key_mgmt);
+ return -1;
+ }
+
+ /* RSN Capabilities */
+ capab = 0;
+#ifdef CONFIG_IEEE80211W
+ if (sm->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC)
+ capab |= WPA_CAPABILITY_MFPC;
+#endif /* CONFIG_IEEE80211W */
+ if (sm->ocv)
+ capab |= WPA_CAPABILITY_OCVC;
+ wpabuf_put_le16(buf, capab);
+
+ /* PMKID Count */
+ wpabuf_put_le16(buf, 1);
+
+ /* PMKID List [PMKR1Name] */
+ wpa_hexdump_key(MSG_DEBUG, "FILS+FT: XXKey (FILS-FT)",
+ sm->fils_ft, sm->fils_ft_len);
+ wpa_hexdump_ascii(MSG_DEBUG, "FILS+FT: SSID", sm->ssid, sm->ssid_len);
+ wpa_hexdump(MSG_DEBUG, "FILS+FT: MDID",
+ sm->mobility_domain, MOBILITY_DOMAIN_ID_LEN);
+ wpa_hexdump_ascii(MSG_DEBUG, "FILS+FT: R0KH-ID",
+ sm->r0kh_id, sm->r0kh_id_len);
+ if (wpa_derive_pmk_r0(sm->fils_ft, sm->fils_ft_len, sm->ssid,
+ sm->ssid_len, sm->mobility_domain,
+ sm->r0kh_id, sm->r0kh_id_len, sm->own_addr,
+ sm->pmk_r0, sm->pmk_r0_name, use_sha384) < 0) {
+ wpa_printf(MSG_WARNING, "FILS+FT: Could not derive PMK-R0");
+ return -1;
+ }
+ sm->pmk_r0_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN;
+ wpa_hexdump_key(MSG_DEBUG, "FILS+FT: PMK-R0",
+ sm->pmk_r0, sm->pmk_r0_len);
+ wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR0Name",
+ sm->pmk_r0_name, WPA_PMK_NAME_LEN);
+ wpa_printf(MSG_DEBUG, "FILS+FT: R1KH-ID: " MACSTR,
+ MAC2STR(sm->r1kh_id));
+ pos = wpabuf_put(buf, WPA_PMK_NAME_LEN);
+ if (wpa_derive_pmk_r1_name(sm->pmk_r0_name, sm->r1kh_id, sm->own_addr,
+ sm->pmk_r1_name, use_sha384) < 0) {
+ wpa_printf(MSG_WARNING, "FILS+FT: Could not derive PMKR1Name");
+ return -1;
+ }
+ wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR1Name", sm->pmk_r1_name,
+ WPA_PMK_NAME_LEN);
+ os_memcpy(pos, sm->pmk_r1_name, WPA_PMK_NAME_LEN);
+
+#ifdef CONFIG_IEEE80211W
+ if (sm->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) {
+ /* Management Group Cipher Suite */
+ pos = wpabuf_put(buf, RSN_SELECTOR_LEN);
+ RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
+ }
+#endif /* CONFIG_IEEE80211W */
+
+ rsnie->len = ((u8 *) wpabuf_put(buf, 0) - (u8 *) rsnie) - 2;
+ return 0;
+}
+#endif /* CONFIG_IEEE80211R */
+
+
+struct wpabuf * fils_build_assoc_req(struct wpa_sm *sm, const u8 **kek,
+ size_t *kek_len, const u8 **snonce,
+ const u8 **anonce,
+ const struct wpabuf **hlp,
+ unsigned int num_hlp)
+{
+ struct wpabuf *buf;
+ size_t len;
+ unsigned int i;
+
+ len = 1000;
+#ifdef CONFIG_IEEE80211R
+ if (sm->fils_ft_ies)
+ len += wpabuf_len(sm->fils_ft_ies);
+ if (wpa_key_mgmt_ft(sm->key_mgmt))
+ len += 256;
+#endif /* CONFIG_IEEE80211R */
+ for (i = 0; hlp && i < num_hlp; i++)
+ len += 10 + wpabuf_len(hlp[i]);
+ buf = wpabuf_alloc(len);
+ if (!buf)
+ return NULL;
+
+#ifdef CONFIG_IEEE80211R
+ if (wpa_key_mgmt_ft(sm->key_mgmt) && sm->fils_ft_ies) {
+ /* MDE and FTE when using FILS+FT */
+ wpabuf_put_buf(buf, sm->fils_ft_ies);
+ /* RSNE with PMKR1Name in PMKID field */
+ if (fils_ft_build_assoc_req_rsne(sm, buf) < 0) {
+ wpabuf_free(buf);
+ return NULL;
+ }
+ }
+#endif /* CONFIG_IEEE80211R */
+
+ /* FILS Session */
+ wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */
+ wpabuf_put_u8(buf, 1 + FILS_SESSION_LEN); /* Length */
+ /* Element ID Extension */
+ wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_SESSION);
+ wpabuf_put_data(buf, sm->fils_session, FILS_SESSION_LEN);
+
+ /* Everything after FILS Session element gets encrypted in the driver
+ * with KEK. The buffer returned from here is the plaintext version. */
+
+ /* TODO: FILS Public Key */
+
+ /* FILS Key Confirm */
+ wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */
+ wpabuf_put_u8(buf, 1 + sm->fils_key_auth_len); /* Length */
+ /* Element ID Extension */
+ wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_KEY_CONFIRM);
+ wpabuf_put_data(buf, sm->fils_key_auth_sta, sm->fils_key_auth_len);
+
+ /* FILS HLP Container */
+ for (i = 0; hlp && i < num_hlp; i++) {
+ const u8 *pos = wpabuf_head(hlp[i]);
+ size_t left = wpabuf_len(hlp[i]);
+
+ wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */
+ if (left <= 254)
+ len = 1 + left;
+ else
+ len = 255;
+ wpabuf_put_u8(buf, len); /* Length */
+ /* Element ID Extension */
+ wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_HLP_CONTAINER);
+ /* Destination MAC Address, Source MAC Address, HLP Packet.
+ * HLP Packet is in MSDU format (i.e., included the LLC/SNAP
+ * header when LPD is used). */
+ wpabuf_put_data(buf, pos, len - 1);
+ pos += len - 1;
+ left -= len - 1;
+ while (left) {
+ wpabuf_put_u8(buf, WLAN_EID_FRAGMENT);
+ len = left > 255 ? 255 : left;
+ wpabuf_put_u8(buf, len);
+ wpabuf_put_data(buf, pos, len);
+ pos += len;
+ left -= len;
+ }
+ }
+
+ /* TODO: FILS IP Address Assignment */
+
+#ifdef CONFIG_OCV
+ if (wpa_sm_ocv_enabled(sm)) {
+ struct wpa_channel_info ci;
+ u8 *pos;
+
+ if (wpa_sm_channel_info(sm, &ci) != 0) {
+ wpa_printf(MSG_WARNING,
+ "FILS: Failed to get channel info for OCI element");
+ wpabuf_free(buf);
+ return NULL;
+ }
+
+ pos = wpabuf_put(buf, OCV_OCI_EXTENDED_LEN);
+ if (ocv_insert_extended_oci(&ci, pos) < 0) {
+ wpabuf_free(buf);
+ return NULL;
+ }
+ }
+#endif /* CONFIG_OCV */
+
+ wpa_hexdump_buf(MSG_DEBUG, "FILS: Association Request plaintext", buf);
+
+ *kek = sm->ptk.kek;
+ *kek_len = sm->ptk.kek_len;
+ wpa_hexdump_key(MSG_DEBUG, "FILS: KEK for AEAD", *kek, *kek_len);
+ *snonce = sm->fils_nonce;
+ wpa_hexdump(MSG_DEBUG, "FILS: SNonce for AEAD AAD",
+ *snonce, FILS_NONCE_LEN);
+ *anonce = sm->fils_anonce;
+ wpa_hexdump(MSG_DEBUG, "FILS: ANonce for AEAD AAD",
+ *anonce, FILS_NONCE_LEN);
+
+ return buf;
+}
+
+
+static void fils_process_hlp_resp(struct wpa_sm *sm, const u8 *resp, size_t len)
+{
+ const u8 *pos, *end;
+
+ wpa_hexdump(MSG_MSGDUMP, "FILS: HLP response", resp, len);
+ if (len < 2 * ETH_ALEN)
+ return;
+ pos = resp + 2 * ETH_ALEN;
+ end = resp + len;
+ if (end - pos >= 6 &&
+ os_memcmp(pos, "\xaa\xaa\x03\x00\x00\x00", 6) == 0)
+ pos += 6; /* Remove SNAP/LLC header */
+ wpa_sm_fils_hlp_rx(sm, resp, resp + ETH_ALEN, pos, end - pos);
+}
+
+
+static void fils_process_hlp_container(struct wpa_sm *sm, const u8 *pos,
+ size_t len)
+{
+ const u8 *end = pos + len;
+ u8 *tmp, *tmp_pos;
+
+ /* Check if there are any FILS HLP Container elements */
+ while (end - pos >= 2) {
+ if (2 + pos[1] > end - pos)
+ return;
+ if (pos[0] == WLAN_EID_EXTENSION &&
+ pos[1] >= 1 + 2 * ETH_ALEN &&
+ pos[2] == WLAN_EID_EXT_FILS_HLP_CONTAINER)
+ break;
+ pos += 2 + pos[1];
+ }
+ if (end - pos < 2)
+ return; /* No FILS HLP Container elements */
+
+ tmp = os_malloc(end - pos);
+ if (!tmp)
+ return;
+
+ while (end - pos >= 2) {
+ if (2 + pos[1] > end - pos ||
+ pos[0] != WLAN_EID_EXTENSION ||
+ pos[1] < 1 + 2 * ETH_ALEN ||
+ pos[2] != WLAN_EID_EXT_FILS_HLP_CONTAINER)
+ break;
+ tmp_pos = tmp;
+ os_memcpy(tmp_pos, pos + 3, pos[1] - 1);
+ tmp_pos += pos[1] - 1;
+ pos += 2 + pos[1];
+
+ /* Add possible fragments */
+ while (end - pos >= 2 && pos[0] == WLAN_EID_FRAGMENT &&
+ 2 + pos[1] <= end - pos) {
+ os_memcpy(tmp_pos, pos + 2, pos[1]);
+ tmp_pos += pos[1];
+ pos += 2 + pos[1];
+ }
+
+ fils_process_hlp_resp(sm, tmp, tmp_pos - tmp);
+ }
+
+ os_free(tmp);
+}
+
+
+int fils_process_assoc_resp(struct wpa_sm *sm, const u8 *resp, size_t len)
+{
+ const struct ieee80211_mgmt *mgmt;
+ const u8 *end, *ie_start;
+ struct ieee802_11_elems elems;
+ int keylen, rsclen;
+ enum wpa_alg alg;
+ struct wpa_gtk_data gd;
+ int maxkeylen;
+ struct wpa_eapol_ie_parse kde;
+
+ if (!sm || !sm->ptk_set) {
+ wpa_printf(MSG_DEBUG, "FILS: No KEK available");
+ return -1;
+ }
+
+ if (!wpa_key_mgmt_fils(sm->key_mgmt)) {
+ wpa_printf(MSG_DEBUG, "FILS: Not a FILS AKM");
+ return -1;
+ }
+
+ if (sm->fils_completed) {
+ wpa_printf(MSG_DEBUG,
+ "FILS: Association has already been completed for this FILS authentication - ignore unexpected retransmission");
+ return -1;
+ }
+
+ wpa_hexdump(MSG_DEBUG, "FILS: (Re)Association Response frame",
+ resp, len);
+
+ mgmt = (const struct ieee80211_mgmt *) resp;
+ if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.assoc_resp))
+ return -1;
+
+ end = resp + len;
+ /* Same offset for Association Response and Reassociation Response */
+ ie_start = mgmt->u.assoc_resp.variable;
+
+ if (ieee802_11_parse_elems(ie_start, end - ie_start, &elems, 1) ==
+ ParseFailed) {
+ wpa_printf(MSG_DEBUG,
+ "FILS: Failed to parse decrypted elements");
+ goto fail;
+ }
+
+ if (!elems.fils_session) {
+ wpa_printf(MSG_DEBUG, "FILS: No FILS Session element");
+ return -1;
+ }
+ if (os_memcmp(elems.fils_session, sm->fils_session,
+ FILS_SESSION_LEN) != 0) {
+ wpa_printf(MSG_DEBUG, "FILS: FILS Session mismatch");
+ wpa_hexdump(MSG_DEBUG, "FILS: Received FILS Session",
+ elems.fils_session, FILS_SESSION_LEN);
+ wpa_hexdump(MSG_DEBUG, "FILS: Expected FILS Session",
+ sm->fils_session, FILS_SESSION_LEN);
+ }
+
+ /* TODO: FILS Public Key */
+
+ if (!elems.fils_key_confirm) {
+ wpa_printf(MSG_DEBUG, "FILS: No FILS Key Confirm element");
+ goto fail;
+ }
+ if (elems.fils_key_confirm_len != sm->fils_key_auth_len) {
+ wpa_printf(MSG_DEBUG,
+ "FILS: Unexpected Key-Auth length %d (expected %d)",
+ elems.fils_key_confirm_len,
+ (int) sm->fils_key_auth_len);
+ goto fail;
+ }
+ if (os_memcmp(elems.fils_key_confirm, sm->fils_key_auth_ap,
+ sm->fils_key_auth_len) != 0) {
+ wpa_printf(MSG_DEBUG, "FILS: Key-Auth mismatch");
+ wpa_hexdump(MSG_DEBUG, "FILS: Received Key-Auth",
+ elems.fils_key_confirm,
+ elems.fils_key_confirm_len);
+ wpa_hexdump(MSG_DEBUG, "FILS: Expected Key-Auth",
+ sm->fils_key_auth_ap, sm->fils_key_auth_len);
+ goto fail;
+ }
+
+#ifdef CONFIG_OCV
+ if (wpa_sm_ocv_enabled(sm)) {
+ struct wpa_channel_info ci;
+
+ if (wpa_sm_channel_info(sm, &ci) != 0) {
+ wpa_printf(MSG_WARNING,
+ "Failed to get channel info to validate received OCI in FILS (Re)Association Response frame");
+ goto fail;
+ }
+
+ if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci,
+ channel_width_to_int(ci.chanwidth),
+ ci.seg1_idx) != 0) {
+ wpa_printf(MSG_WARNING, "FILS: %s", ocv_errorstr);
+ goto fail;
+ }
+ }
+#endif /* CONFIG_OCV */
+
+#ifdef CONFIG_IEEE80211R
+ if (wpa_key_mgmt_ft(sm->key_mgmt) && sm->fils_ft_ies) {
+ struct wpa_ie_data rsn;
+
+ /* Check that PMKR1Name derived by the AP matches */
+ if (!elems.rsn_ie ||
+ wpa_parse_wpa_ie_rsn(elems.rsn_ie - 2, elems.rsn_ie_len + 2,
+ &rsn) < 0 ||
+ !rsn.pmkid || rsn.num_pmkid != 1 ||
+ os_memcmp(rsn.pmkid, sm->pmk_r1_name,
+ WPA_PMK_NAME_LEN) != 0) {
+ wpa_printf(MSG_DEBUG,
+ "FILS+FT: No RSNE[PMKR1Name] match in AssocResp");
+ goto fail;
+ }
+ }
+#endif /* CONFIG_IEEE80211R */
+
+ /* Key Delivery */
+ if (!elems.key_delivery) {
+ wpa_printf(MSG_DEBUG, "FILS: No Key Delivery element");
+ goto fail;
+ }
+
+ /* Parse GTK and set the key to the driver */
+ os_memset(&gd, 0, sizeof(gd));
+ if (wpa_supplicant_parse_ies(elems.key_delivery + WPA_KEY_RSC_LEN,
+ elems.key_delivery_len - WPA_KEY_RSC_LEN,
+ &kde) < 0) {
+ wpa_printf(MSG_DEBUG, "FILS: Failed to parse KDEs");
+ goto fail;
+ }
+ if (!kde.gtk) {
+ wpa_printf(MSG_DEBUG, "FILS: No GTK KDE");
+ goto fail;
+ }
+ maxkeylen = gd.gtk_len = kde.gtk_len - 2;
+ if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
+ gd.gtk_len, maxkeylen,
+ &gd.key_rsc_len, &gd.alg))
+ goto fail;
+
+ wpa_hexdump_key(MSG_DEBUG, "FILS: Received GTK", kde.gtk, kde.gtk_len);
+ gd.keyidx = kde.gtk[0] & 0x3;
+ gd.tx = wpa_supplicant_gtk_tx_bit_workaround(sm,
+ !!(kde.gtk[0] & BIT(2)));
+ if (kde.gtk_len - 2 > sizeof(gd.gtk)) {
+ wpa_printf(MSG_DEBUG, "FILS: Too long GTK in GTK KDE (len=%lu)",
+ (unsigned long) kde.gtk_len - 2);
+ goto fail;
+ }
+ os_memcpy(gd.gtk, kde.gtk + 2, kde.gtk_len - 2);
+
+ wpa_printf(MSG_DEBUG, "FILS: Set GTK to driver");
+ if (wpa_supplicant_install_gtk(sm, &gd, elems.key_delivery, 0) < 0) {
+ wpa_printf(MSG_DEBUG, "FILS: Failed to set GTK");
+ goto fail;
+ }
+
+ if (ieee80211w_set_keys(sm, &kde) < 0) {
+ wpa_printf(MSG_DEBUG, "FILS: Failed to set IGTK");
+ goto fail;
+ }
+
+ alg = wpa_cipher_to_alg(sm->pairwise_cipher);
+ keylen = wpa_cipher_key_len(sm->pairwise_cipher);
+ if (keylen <= 0 || (unsigned int) keylen != sm->ptk.tk_len) {
+ wpa_printf(MSG_DEBUG, "FILS: TK length mismatch: %u != %lu",
+ keylen, (long unsigned int) sm->ptk.tk_len);
+ goto fail;
+ }
+ rsclen = wpa_cipher_rsc_len(sm->pairwise_cipher);
+ wpa_hexdump_key(MSG_DEBUG, "FILS: Set TK to driver",
+ sm->ptk.tk, keylen);
+ if (wpa_sm_set_key(sm, alg, sm->bssid, 0, 1, null_rsc, rsclen,
+ sm->ptk.tk, keylen) < 0) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "FILS: Failed to set PTK to the driver (alg=%d keylen=%d bssid="
+ MACSTR ")",
+ alg, keylen, MAC2STR(sm->bssid));
+ goto fail;
+ }
+
+ /* TODO: TK could be cleared after auth frame exchange now that driver
+ * takes care of association frame encryption/decryption. */
+ /* TK is not needed anymore in supplicant */
+ os_memset(sm->ptk.tk, 0, WPA_TK_MAX_LEN);
+ sm->ptk.tk_len = 0;
+ sm->ptk.installed = 1;
+
+ /* FILS HLP Container */
+ fils_process_hlp_container(sm, ie_start, end - ie_start);
+
+ /* TODO: FILS IP Address Assignment */
+
+ wpa_printf(MSG_DEBUG, "FILS: Auth+Assoc completed successfully");
+ sm->fils_completed = 1;
+
+ return 0;
+fail:
+ return -1;
+}
+
+
+void wpa_sm_set_reset_fils_completed(struct wpa_sm *sm, int set)
+{
+ if (sm)
+ sm->fils_completed = !!set;
+}
+
+#endif /* CONFIG_FILS */
+
+
+int wpa_fils_is_completed(struct wpa_sm *sm)
+{
+#ifdef CONFIG_FILS
+ return sm && sm->fils_completed;
+#else /* CONFIG_FILS */
+ return 0;
+#endif /* CONFIG_FILS */
+}
+
+
+#ifdef CONFIG_OWE
+
+struct wpabuf * owe_build_assoc_req(struct wpa_sm *sm, u16 group)
+{
+ struct wpabuf *ie = NULL, *pub = NULL;
+ size_t prime_len;
+
+ if (group == 19)
+ prime_len = 32;
+ else if (group == 20)
+ prime_len = 48;
+ else if (group == 21)
+ prime_len = 66;
+ else
+ return NULL;
+
+ crypto_ecdh_deinit(sm->owe_ecdh);
+ sm->owe_ecdh = crypto_ecdh_init(group);
+ if (!sm->owe_ecdh)
+ goto fail;
+ sm->owe_group = group;
+ pub = crypto_ecdh_get_pubkey(sm->owe_ecdh, 0);
+ pub = wpabuf_zeropad(pub, prime_len);
+ if (!pub)
+ goto fail;
+
+ ie = wpabuf_alloc(5 + wpabuf_len(pub));
+ if (!ie)
+ goto fail;
+ wpabuf_put_u8(ie, WLAN_EID_EXTENSION);
+ wpabuf_put_u8(ie, 1 + 2 + wpabuf_len(pub));
+ wpabuf_put_u8(ie, WLAN_EID_EXT_OWE_DH_PARAM);
+ wpabuf_put_le16(ie, group);
+ wpabuf_put_buf(ie, pub);
+ wpabuf_free(pub);
+ wpa_hexdump_buf(MSG_DEBUG, "OWE: Diffie-Hellman Parameter element",
+ ie);
+
+ return ie;
+fail:
+ wpabuf_free(pub);
+ crypto_ecdh_deinit(sm->owe_ecdh);
+ sm->owe_ecdh = NULL;
+ return NULL;
+}
+
+
+int owe_process_assoc_resp(struct wpa_sm *sm, const u8 *bssid,
+ const u8 *resp_ies, size_t resp_ies_len)
+{
+ struct ieee802_11_elems elems;
+ u16 group;
+ struct wpabuf *secret, *pub, *hkey;
+ int res;
+ u8 prk[SHA512_MAC_LEN], pmkid[SHA512_MAC_LEN];
+ const char *info = "OWE Key Generation";
+ const u8 *addr[2];
+ size_t len[2];
+ size_t hash_len, prime_len;
+ struct wpa_ie_data data;
+
+ if (!resp_ies ||
+ ieee802_11_parse_elems(resp_ies, resp_ies_len, &elems, 1) ==
+ ParseFailed) {
+ wpa_printf(MSG_INFO,
+ "OWE: Could not parse Association Response frame elements");
+ return -1;
+ }
+
+ if (sm->cur_pmksa && elems.rsn_ie &&
+ wpa_parse_wpa_ie_rsn(elems.rsn_ie - 2, 2 + elems.rsn_ie_len,
+ &data) == 0 &&
+ data.num_pmkid == 1 && data.pmkid &&
+ os_memcmp(sm->cur_pmksa->pmkid, data.pmkid, PMKID_LEN) == 0) {
+ wpa_printf(MSG_DEBUG, "OWE: Use PMKSA caching");
+ wpa_sm_set_pmk_from_pmksa(sm);
+ return 0;
+ }
+
+ if (!elems.owe_dh) {
+ wpa_printf(MSG_INFO,
+ "OWE: No Diffie-Hellman Parameter element found in Association Response frame");
+ return -1;
+ }
+
+ group = WPA_GET_LE16(elems.owe_dh);
+ if (group != sm->owe_group) {
+ wpa_printf(MSG_INFO,
+ "OWE: Unexpected Diffie-Hellman group in response: %u",
+ group);
+ return -1;
+ }
+
+ if (!sm->owe_ecdh) {
+ wpa_printf(MSG_INFO, "OWE: No ECDH state available");
+ return -1;
+ }
+
+ if (group == 19)
+ prime_len = 32;
+ else if (group == 20)
+ prime_len = 48;
+ else if (group == 21)
+ prime_len = 66;
+ else
+ return -1;
+
+ secret = crypto_ecdh_set_peerkey(sm->owe_ecdh, 0,
+ elems.owe_dh + 2,
+ elems.owe_dh_len - 2);
+ secret = wpabuf_zeropad(secret, prime_len);
+ if (!secret) {
+ wpa_printf(MSG_DEBUG, "OWE: Invalid peer DH public key");
+ return -1;
+ }
+ wpa_hexdump_buf_key(MSG_DEBUG, "OWE: DH shared secret", secret);
+
+ /* prk = HKDF-extract(C | A | group, z) */
+
+ pub = crypto_ecdh_get_pubkey(sm->owe_ecdh, 0);
+ if (!pub) {
+ wpabuf_clear_free(secret);
+ return -1;
+ }
+
+ /* PMKID = Truncate-128(Hash(C | A)) */
+ addr[0] = wpabuf_head(pub);
+ len[0] = wpabuf_len(pub);
+ addr[1] = elems.owe_dh + 2;
+ len[1] = elems.owe_dh_len - 2;
+ if (group == 19) {
+ res = sha256_vector(2, addr, len, pmkid);
+ hash_len = SHA256_MAC_LEN;
+ } else if (group == 20) {
+ res = sha384_vector(2, addr, len, pmkid);
+ hash_len = SHA384_MAC_LEN;
+ } else if (group == 21) {
+ res = sha512_vector(2, addr, len, pmkid);
+ hash_len = SHA512_MAC_LEN;
+ } else {
+ res = -1;
+ hash_len = 0;
+ }
+ pub = wpabuf_zeropad(pub, prime_len);
+ if (res < 0 || !pub) {
+ wpabuf_free(pub);
+ wpabuf_clear_free(secret);
+ return -1;
+ }
+
+ hkey = wpabuf_alloc(wpabuf_len(pub) + elems.owe_dh_len - 2 + 2);
+ if (!hkey) {
+ wpabuf_free(pub);
+ wpabuf_clear_free(secret);
+ return -1;
+ }
+
+ wpabuf_put_buf(hkey, pub); /* C */
+ wpabuf_free(pub);
+ wpabuf_put_data(hkey, elems.owe_dh + 2, elems.owe_dh_len - 2); /* A */
+ wpabuf_put_le16(hkey, sm->owe_group); /* group */
+ if (group == 19)
+ res = hmac_sha256(wpabuf_head(hkey), wpabuf_len(hkey),
+ wpabuf_head(secret), wpabuf_len(secret), prk);
+ else if (group == 20)
+ res = hmac_sha384(wpabuf_head(hkey), wpabuf_len(hkey),
+ wpabuf_head(secret), wpabuf_len(secret), prk);
+ else if (group == 21)
+ res = hmac_sha512(wpabuf_head(hkey), wpabuf_len(hkey),
+ wpabuf_head(secret), wpabuf_len(secret), prk);
+ wpabuf_clear_free(hkey);
+ wpabuf_clear_free(secret);
+ if (res < 0)
+ return -1;
+
+ wpa_hexdump_key(MSG_DEBUG, "OWE: prk", prk, hash_len);
+
+ /* PMK = HKDF-expand(prk, "OWE Key Generation", n) */
+
+ if (group == 19)
+ res = hmac_sha256_kdf(prk, hash_len, NULL, (const u8 *) info,
+ os_strlen(info), sm->pmk, hash_len);
+ else if (group == 20)
+ res = hmac_sha384_kdf(prk, hash_len, NULL, (const u8 *) info,
+ os_strlen(info), sm->pmk, hash_len);
+ else if (group == 21)
+ res = hmac_sha512_kdf(prk, hash_len, NULL, (const u8 *) info,
+ os_strlen(info), sm->pmk, hash_len);
+ os_memset(prk, 0, SHA512_MAC_LEN);
+ if (res < 0) {
+ sm->pmk_len = 0;
+ return -1;
+ }
+ sm->pmk_len = hash_len;
+
+ wpa_hexdump_key(MSG_DEBUG, "OWE: PMK", sm->pmk, sm->pmk_len);
+ wpa_hexdump(MSG_DEBUG, "OWE: PMKID", pmkid, PMKID_LEN);
+ pmksa_cache_add(sm->pmksa, sm->pmk, sm->pmk_len, pmkid, NULL, 0,
+ bssid, sm->own_addr, sm->network_ctx, sm->key_mgmt,
+ NULL);
+
+ return 0;
+}
+
+#endif /* CONFIG_OWE */
+
+
+void wpa_sm_set_fils_cache_id(struct wpa_sm *sm, const u8 *fils_cache_id)
+{
+#ifdef CONFIG_FILS
+ if (sm && fils_cache_id) {
+ sm->fils_cache_id_set = 1;
+ os_memcpy(sm->fils_cache_id, fils_cache_id, FILS_CACHE_ID_LEN);
+ }
+#endif /* CONFIG_FILS */
+}
+
+
+#ifdef CONFIG_DPP2
+void wpa_sm_set_dpp_z(struct wpa_sm *sm, const struct wpabuf *z)
+{
+ if (sm) {
+ wpabuf_clear_free(sm->dpp_z);
+ sm->dpp_z = z ? wpabuf_dup(z) : NULL;
+ }
+}
+#endif /* CONFIG_DPP2 */
diff --git a/freebsd/contrib/wpa/src/rsn_supp/wpa.h b/freebsd/contrib/wpa/src/rsn_supp/wpa.h
index 0b7477f3..8903f8e1 100644
--- a/freebsd/contrib/wpa/src/rsn_supp/wpa.h
+++ b/freebsd/contrib/wpa/src/rsn_supp/wpa.h
@@ -18,6 +18,7 @@ struct wpa_sm;
struct eapol_sm;
struct wpa_config_blob;
struct hostapd_freq_params;
+struct wpa_channel_info;
struct wpa_sm_ctx {
void *ctx; /* pointer to arbitrary upper level context */
@@ -25,7 +26,7 @@ struct wpa_sm_ctx {
void (*set_state)(void *ctx, enum wpa_states state);
enum wpa_states (*get_state)(void *ctx);
- void (*deauthenticate)(void * ctx, int reason_code);
+ void (*deauthenticate)(void * ctx, int reason_code);
int (*set_key)(void *ctx, enum wpa_alg alg,
const u8 *addr, int key_idx, int set_tx,
const u8 *seq, size_t seq_len,
@@ -38,8 +39,11 @@ struct wpa_sm_ctx {
void (*cancel_auth_timeout)(void *ctx);
u8 * (*alloc_eapol)(void *ctx, u8 type, const void *data, u16 data_len,
size_t *msg_len, void **data_pos);
- int (*add_pmkid)(void *ctx, const u8 *bssid, const u8 *pmkid);
- int (*remove_pmkid)(void *ctx, const u8 *bssid, const u8 *pmkid);
+ int (*add_pmkid)(void *ctx, void *network_ctx, const u8 *bssid,
+ const u8 *pmkid, const u8 *fils_cache_id,
+ const u8 *pmk, size_t pmk_len);
+ int (*remove_pmkid)(void *ctx, void *network_ctx, const u8 *bssid,
+ const u8 *pmkid, const u8 *fils_cache_id);
void (*set_config_blob)(void *ctx, struct wpa_config_blob *blob);
const struct wpa_config_blob * (*get_config_blob)(void *ctx,
const char *name);
@@ -77,6 +81,9 @@ struct wpa_sm_ctx {
const u8 *kck, size_t kck_len,
const u8 *replay_ctr);
int (*key_mgmt_set_pmk)(void *ctx, const u8 *pmk, size_t pmk_len);
+ void (*fils_hlp_rx)(void *ctx, const u8 *dst, const u8 *src,
+ const u8 *pkt, size_t pkt_len);
+ int (*channel_info)(void *ctx, struct wpa_channel_info *ci);
};
@@ -90,12 +97,12 @@ enum wpa_sm_conf_params {
WPA_PARAM_KEY_MGMT,
WPA_PARAM_MGMT_GROUP,
WPA_PARAM_RSN_ENABLED,
- WPA_PARAM_MFP
+ WPA_PARAM_MFP,
+ WPA_PARAM_OCV
};
struct rsn_supp_config {
void *network_ctx;
- int peerkey_enabled;
int allowed_pairwise_cipher; /* bitfield of WPA_CIPHER_* */
int proactive_key_caching;
int eap_workaround;
@@ -105,6 +112,7 @@ struct rsn_supp_config {
int wpa_ptk_rekey;
int p2p;
int wpa_rsc_relaxation;
+ const u8 *fils_cache_id;
};
#ifndef CONFIG_NO_WPA
@@ -136,6 +144,7 @@ int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param,
int wpa_sm_get_status(struct wpa_sm *sm, char *buf, size_t buflen,
int verbose);
int wpa_sm_pmf_enabled(struct wpa_sm *sm);
+int wpa_sm_ocv_enabled(struct wpa_sm *sm);
void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise);
@@ -147,6 +156,15 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
const u8 *buf, size_t len);
int wpa_sm_parse_own_wpa_ie(struct wpa_sm *sm, struct wpa_ie_data *data);
int wpa_sm_pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len);
+struct rsn_pmksa_cache_entry * wpa_sm_pmksa_cache_head(struct wpa_sm *sm);
+struct rsn_pmksa_cache_entry *
+wpa_sm_pmksa_cache_add_entry(struct wpa_sm *sm,
+ struct rsn_pmksa_cache_entry * entry);
+void wpa_sm_pmksa_cache_add(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len,
+ const u8 *pmkid, const u8 *bssid,
+ const u8 *fils_cache_id);
+int wpa_sm_pmksa_exists(struct wpa_sm *sm, const u8 *bssid,
+ const void *network_ctx);
void wpa_sm_drop_sa(struct wpa_sm *sm);
int wpa_sm_has_ptk(struct wpa_sm *sm);
@@ -160,6 +178,7 @@ void wpa_sm_set_rx_replay_ctr(struct wpa_sm *sm, const u8 *rx_replay_counter);
void wpa_sm_set_ptk_kck_kek(struct wpa_sm *sm,
const u8 *ptk_kck, size_t ptk_kck_len,
const u8 *ptk_kek, size_t ptk_kek_len);
+int wpa_fils_is_completed(struct wpa_sm *sm);
#else /* CONFIG_NO_WPA */
@@ -264,6 +283,11 @@ static inline int wpa_sm_pmf_enabled(struct wpa_sm *sm)
return 0;
}
+static inline int wpa_sm_ocv_enabled(struct wpa_sm *sm)
+{
+ return 0;
+}
+
static inline void wpa_sm_key_request(struct wpa_sm *sm, int error,
int pairwise)
{
@@ -327,29 +351,20 @@ static inline void wpa_sm_set_ptk_kck_kek(struct wpa_sm *sm, const u8 *ptk_kck,
{
}
-#endif /* CONFIG_NO_WPA */
-
-#ifdef CONFIG_PEERKEY
-int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer);
-int wpa_sm_rx_eapol_peerkey(struct wpa_sm *sm, const u8 *src_addr,
- const u8 *buf, size_t len);
-#else /* CONFIG_PEERKEY */
-static inline int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer)
-{
- return -1;
-}
-
-static inline int wpa_sm_rx_eapol_peerkey(struct wpa_sm *sm, const u8 *src_addr,
- const u8 *buf, size_t len)
+static inline int wpa_fils_is_completed(struct wpa_sm *sm)
{
return 0;
}
-#endif /* CONFIG_PEERKEY */
+
+#endif /* CONFIG_NO_WPA */
#ifdef CONFIG_IEEE80211R
int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len);
int wpa_ft_prepare_auth_request(struct wpa_sm *sm, const u8 *mdie);
+int wpa_ft_add_mdie(struct wpa_sm *sm, u8 *ies, size_t ies_len,
+ const u8 *mdie);
+const u8 * wpa_sm_get_ft_md(struct wpa_sm *sm);
int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
int ft_action, const u8 *target_ap,
const u8 *ric_ies, size_t ric_ies_len);
@@ -374,6 +389,12 @@ static inline int wpa_ft_prepare_auth_request(struct wpa_sm *sm,
return 0;
}
+static inline int wpa_ft_add_mdie(struct wpa_sm *sm, u8 *ies, size_t ies_len,
+ const u8 *mdie)
+{
+ return 0;
+}
+
static inline int
wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
int ft_action, const u8 *target_ap)
@@ -425,5 +446,25 @@ extern unsigned int tdls_testing;
int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf);
void wpa_sm_set_test_assoc_ie(struct wpa_sm *sm, struct wpabuf *buf);
+const u8 * wpa_sm_get_anonce(struct wpa_sm *sm);
+unsigned int wpa_sm_get_key_mgmt(struct wpa_sm *sm);
+
+struct wpabuf * fils_build_auth(struct wpa_sm *sm, int dh_group, const u8 *md);
+int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
+ size_t len);
+struct wpabuf * fils_build_assoc_req(struct wpa_sm *sm, const u8 **kek,
+ size_t *kek_len, const u8 **snonce,
+ const u8 **anonce,
+ const struct wpabuf **hlp,
+ unsigned int num_hlp);
+int fils_process_assoc_resp(struct wpa_sm *sm, const u8 *resp, size_t len);
+
+struct wpabuf * owe_build_assoc_req(struct wpa_sm *sm, u16 group);
+int owe_process_assoc_resp(struct wpa_sm *sm, const u8 *bssid,
+ const u8 *resp_ies, size_t resp_ies_len);
+
+void wpa_sm_set_reset_fils_completed(struct wpa_sm *sm, int set);
+void wpa_sm_set_fils_cache_id(struct wpa_sm *sm, const u8 *fils_cache_id);
+void wpa_sm_set_dpp_z(struct wpa_sm *sm, const struct wpabuf *z);
#endif /* WPA_H */
diff --git a/freebsd/contrib/wpa/src/rsn_supp/wpa_ft.c b/freebsd/contrib/wpa/src/rsn_supp/wpa_ft.c
index ea5b419f..6738b05b 100644
--- a/freebsd/contrib/wpa/src/rsn_supp/wpa_ft.c
+++ b/freebsd/contrib/wpa/src/rsn_supp/wpa_ft.c
@@ -2,7 +2,7 @@
/*
* WPA Supplicant - IEEE 802.11r - Fast BSS Transition
- * Copyright (c) 2006-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2006-2018, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -12,9 +12,12 @@
#include "common.h"
#include "crypto/aes_wrap.h"
+#include "crypto/sha384.h"
#include "crypto/random.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
+#include "common/ocv.h"
+#include "drivers/driver.h"
#include "wpa.h"
#include "wpa_i.h"
@@ -25,6 +28,7 @@ int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
{
u8 ptk_name[WPA_PMK_NAME_LEN];
const u8 *anonce = key->key_nonce;
+ int use_sha384 = wpa_key_mgmt_sha384(sm->key_mgmt);
if (sm->xxkey_len == 0) {
wpa_printf(MSG_DEBUG, "FT: XXKey not available for key "
@@ -32,21 +36,26 @@ int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
return -1;
}
- wpa_derive_pmk_r0(sm->xxkey, sm->xxkey_len, sm->ssid,
- sm->ssid_len, sm->mobility_domain,
- sm->r0kh_id, sm->r0kh_id_len, sm->own_addr,
- sm->pmk_r0, sm->pmk_r0_name);
- wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", sm->pmk_r0, PMK_LEN);
+ sm->pmk_r0_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN;
+ if (wpa_derive_pmk_r0(sm->xxkey, sm->xxkey_len, sm->ssid,
+ sm->ssid_len, sm->mobility_domain,
+ sm->r0kh_id, sm->r0kh_id_len, sm->own_addr,
+ sm->pmk_r0, sm->pmk_r0_name, use_sha384) < 0)
+ return -1;
+ wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", sm->pmk_r0, sm->pmk_r0_len);
wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name",
sm->pmk_r0_name, WPA_PMK_NAME_LEN);
- wpa_derive_pmk_r1(sm->pmk_r0, sm->pmk_r0_name, sm->r1kh_id,
- sm->own_addr, sm->pmk_r1, sm->pmk_r1_name);
- wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", sm->pmk_r1, PMK_LEN);
+ sm->pmk_r1_len = sm->pmk_r0_len;
+ if (wpa_derive_pmk_r1(sm->pmk_r0, sm->pmk_r0_len, sm->pmk_r0_name,
+ sm->r1kh_id, sm->own_addr, sm->pmk_r1,
+ sm->pmk_r1_name) < 0)
+ return -1;
+ wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", sm->pmk_r1, sm->pmk_r1_len);
wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", sm->pmk_r1_name,
WPA_PMK_NAME_LEN);
- return wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, anonce, sm->own_addr,
- sm->bssid, sm->pmk_r1_name, ptk, ptk_name,
- sm->key_mgmt, sm->pairwise_cipher);
+ return wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len, sm->snonce, anonce,
+ sm->own_addr, sm->bssid, sm->pmk_r1_name, ptk,
+ ptk_name, sm->key_mgmt, sm->pairwise_cipher);
}
@@ -60,11 +69,13 @@ int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len)
{
struct wpa_ft_ies ft;
+ int use_sha384;
if (sm == NULL)
return 0;
- if (wpa_ft_parse_ies(ies, ies_len, &ft) < 0)
+ use_sha384 = wpa_key_mgmt_sha384(sm->key_mgmt);
+ if (wpa_ft_parse_ies(ies, ies_len, &ft, use_sha384) < 0)
return -1;
if (ft.mdie && ft.mdie_len < MOBILITY_DOMAIN_ID_LEN + 1)
@@ -148,16 +159,17 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
const u8 *ap_mdie)
{
size_t buf_len;
- u8 *buf, *pos, *ftie_len, *ftie_pos;
+ u8 *buf, *pos, *ftie_len, *ftie_pos, *fte_mic, *elem_count;
struct rsn_mdie *mdie;
- struct rsn_ftie *ftie;
struct rsn_ie_hdr *rsnie;
u16 capab;
+ int mdie_len;
sm->ft_completed = 0;
sm->ft_reassoc_completed = 0;
- buf_len = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) +
+ buf_len = 2 + sizeof(struct rsn_mdie) + 2 +
+ sizeof(struct rsn_ftie_sha384) +
2 + sm->r0kh_id_len + ric_ies_len + 100;
buf = os_zalloc(buf_len);
if (buf == NULL)
@@ -203,10 +215,20 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
/* Authenticated Key Management Suite List */
if (sm->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X)
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X);
+#ifdef CONFIG_SHA384
+ else if (sm->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X_SHA384)
+ RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384);
+#endif /* CONFIG_SHA384 */
else if (sm->key_mgmt == WPA_KEY_MGMT_FT_PSK)
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK);
else if (sm->key_mgmt == WPA_KEY_MGMT_FT_SAE)
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE);
+#ifdef CONFIG_FILS
+ else if (sm->key_mgmt == WPA_KEY_MGMT_FT_FILS_SHA256)
+ RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA256);
+ else if (sm->key_mgmt == WPA_KEY_MGMT_FT_FILS_SHA384)
+ RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA384);
+#endif /* CONFIG_FILS */
else {
wpa_printf(MSG_WARNING, "FT: Invalid key management type (%d)",
sm->key_mgmt);
@@ -218,9 +240,14 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
/* RSN Capabilities */
capab = 0;
#ifdef CONFIG_IEEE80211W
- if (sm->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC)
+ if (sm->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC ||
+ sm->mgmt_group_cipher == WPA_CIPHER_BIP_GMAC_128 ||
+ sm->mgmt_group_cipher == WPA_CIPHER_BIP_GMAC_256 ||
+ sm->mgmt_group_cipher == WPA_CIPHER_BIP_CMAC_256)
capab |= WPA_CAPABILITY_MFPC;
#endif /* CONFIG_IEEE80211W */
+ if (sm->ocv)
+ capab |= WPA_CAPABILITY_OCVC;
WPA_PUT_LE16(pos, capab);
pos += 2;
@@ -233,34 +260,63 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
pos += WPA_PMK_NAME_LEN;
#ifdef CONFIG_IEEE80211W
- if (sm->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) {
- /* Management Group Cipher Suite */
+ /* Management Group Cipher Suite */
+ switch (sm->mgmt_group_cipher) {
+ case WPA_CIPHER_AES_128_CMAC:
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
pos += RSN_SELECTOR_LEN;
+ break;
+ case WPA_CIPHER_BIP_GMAC_128:
+ RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_GMAC_128);
+ pos += RSN_SELECTOR_LEN;
+ break;
+ case WPA_CIPHER_BIP_GMAC_256:
+ RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_GMAC_256);
+ pos += RSN_SELECTOR_LEN;
+ break;
+ case WPA_CIPHER_BIP_CMAC_256:
+ RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_CMAC_256);
+ pos += RSN_SELECTOR_LEN;
+ break;
}
#endif /* CONFIG_IEEE80211W */
rsnie->len = (pos - (u8 *) rsnie) - 2;
/* MDIE */
- *pos++ = WLAN_EID_MOBILITY_DOMAIN;
- *pos++ = sizeof(*mdie);
- mdie = (struct rsn_mdie *) pos;
- pos += sizeof(*mdie);
- os_memcpy(mdie->mobility_domain, sm->mobility_domain,
- MOBILITY_DOMAIN_ID_LEN);
- mdie->ft_capab = ap_mdie && ap_mdie[1] >= 3 ? ap_mdie[4] :
- sm->mdie_ft_capab;
+ mdie_len = wpa_ft_add_mdie(sm, pos, buf_len - (pos - buf), ap_mdie);
+ if (mdie_len <= 0) {
+ os_free(buf);
+ return NULL;
+ }
+ mdie = (struct rsn_mdie *) (pos + 2);
+ pos += mdie_len;
/* FTIE[SNonce, [R1KH-ID,] R0KH-ID ] */
ftie_pos = pos;
*pos++ = WLAN_EID_FAST_BSS_TRANSITION;
ftie_len = pos++;
- ftie = (struct rsn_ftie *) pos;
- pos += sizeof(*ftie);
- os_memcpy(ftie->snonce, sm->snonce, WPA_NONCE_LEN);
- if (anonce)
- os_memcpy(ftie->anonce, anonce, WPA_NONCE_LEN);
+ if (wpa_key_mgmt_sha384(sm->key_mgmt)) {
+ struct rsn_ftie_sha384 *ftie;
+
+ ftie = (struct rsn_ftie_sha384 *) pos;
+ fte_mic = ftie->mic;
+ elem_count = &ftie->mic_control[1];
+ pos += sizeof(*ftie);
+ os_memcpy(ftie->snonce, sm->snonce, WPA_NONCE_LEN);
+ if (anonce)
+ os_memcpy(ftie->anonce, anonce, WPA_NONCE_LEN);
+ } else {
+ struct rsn_ftie *ftie;
+
+ ftie = (struct rsn_ftie *) pos;
+ fte_mic = ftie->mic;
+ elem_count = &ftie->mic_control[1];
+ pos += sizeof(*ftie);
+ os_memcpy(ftie->snonce, sm->snonce, WPA_NONCE_LEN);
+ if (anonce)
+ os_memcpy(ftie->anonce, anonce, WPA_NONCE_LEN);
+ }
if (kck) {
/* R1KH-ID sub-element in third FT message */
*pos++ = FTIE_SUBELEM_R1KH_ID;
@@ -273,6 +329,26 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
*pos++ = sm->r0kh_id_len;
os_memcpy(pos, sm->r0kh_id, sm->r0kh_id_len);
pos += sm->r0kh_id_len;
+#ifdef CONFIG_OCV
+ if (kck && wpa_sm_ocv_enabled(sm)) {
+ /* OCI sub-element in the third FT message */
+ struct wpa_channel_info ci;
+
+ if (wpa_sm_channel_info(sm, &ci) != 0) {
+ wpa_printf(MSG_WARNING,
+ "Failed to get channel info for OCI element in FTE");
+ os_free(buf);
+ return NULL;
+ }
+
+ *pos++ = FTIE_SUBELEM_OCI;
+ *pos++ = OCV_OCI_LEN;
+ if (ocv_insert_oci(&ci, &pos) < 0) {
+ os_free(buf);
+ return NULL;
+ }
+ }
+#endif /* CONFIG_OCV */
*ftie_len = pos - ftie_len - 1;
if (ric_ies) {
@@ -294,13 +370,12 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
* RIC-Request (if present)
*/
/* Information element count */
- ftie->mic_control[1] = 3 + ieee802_11_ie_count(ric_ies,
- ric_ies_len);
+ *elem_count = 3 + ieee802_11_ie_count(ric_ies, ric_ies_len);
if (wpa_ft_mic(kck, kck_len, sm->own_addr, target_ap, 5,
((u8 *) mdie) - 2, 2 + sizeof(*mdie),
ftie_pos, 2 + *ftie_len,
(u8 *) rsnie, 2 + rsnie->len, ric_ies,
- ric_ies_len, ftie->mic) < 0) {
+ ric_ies_len, fte_mic) < 0) {
wpa_printf(MSG_INFO, "FT: Failed to calculate MIC");
os_free(buf);
return NULL;
@@ -369,6 +444,37 @@ int wpa_ft_prepare_auth_request(struct wpa_sm *sm, const u8 *mdie)
}
+int wpa_ft_add_mdie(struct wpa_sm *sm, u8 *buf, size_t buf_len,
+ const u8 *ap_mdie)
+{
+ u8 *pos = buf;
+ struct rsn_mdie *mdie;
+
+ if (buf_len < 2 + sizeof(*mdie)) {
+ wpa_printf(MSG_INFO,
+ "FT: Failed to add MDIE: short buffer, length=%zu",
+ buf_len);
+ return 0;
+ }
+
+ *pos++ = WLAN_EID_MOBILITY_DOMAIN;
+ *pos++ = sizeof(*mdie);
+ mdie = (struct rsn_mdie *) pos;
+ os_memcpy(mdie->mobility_domain, sm->mobility_domain,
+ MOBILITY_DOMAIN_ID_LEN);
+ mdie->ft_capab = ap_mdie && ap_mdie[1] >= 3 ? ap_mdie[4] :
+ sm->mdie_ft_capab;
+
+ return 2 + sizeof(*mdie);
+}
+
+
+const u8 * wpa_sm_get_ft_md(struct wpa_sm *sm)
+{
+ return sm->mobility_domain;
+}
+
+
int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
int ft_action, const u8 *target_ap,
const u8 *ric_ies, size_t ric_ies_len)
@@ -377,10 +483,13 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
size_t ft_ies_len;
struct wpa_ft_ies parse;
struct rsn_mdie *mdie;
- struct rsn_ftie *ftie;
u8 ptk_name[WPA_PMK_NAME_LEN];
int ret;
const u8 *bssid;
+ const u8 *kck;
+ size_t kck_len;
+ int use_sha384 = wpa_key_mgmt_sha384(sm->key_mgmt);
+ const u8 *anonce, *snonce;
wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_len);
wpa_hexdump(MSG_DEBUG, "FT: RIC IEs", ric_ies, ric_ies_len);
@@ -406,7 +515,7 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
return -1;
}
- if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) {
+ if (wpa_ft_parse_ies(ies, ies_len, &parse, use_sha384) < 0) {
wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs");
return -1;
}
@@ -419,16 +528,34 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
return -1;
}
- ftie = (struct rsn_ftie *) parse.ftie;
- if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) {
- wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
- return -1;
+ if (use_sha384) {
+ struct rsn_ftie_sha384 *ftie;
+
+ ftie = (struct rsn_ftie_sha384 *) parse.ftie;
+ if (!ftie || parse.ftie_len < sizeof(*ftie)) {
+ wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
+ return -1;
+ }
+
+ anonce = ftie->anonce;
+ snonce = ftie->snonce;
+ } else {
+ struct rsn_ftie *ftie;
+
+ ftie = (struct rsn_ftie *) parse.ftie;
+ if (!ftie || parse.ftie_len < sizeof(*ftie)) {
+ wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
+ return -1;
+ }
+
+ anonce = ftie->anonce;
+ snonce = ftie->snonce;
}
- if (os_memcmp(ftie->snonce, sm->snonce, WPA_NONCE_LEN) != 0) {
+ if (os_memcmp(snonce, sm->snonce, WPA_NONCE_LEN) != 0) {
wpa_printf(MSG_DEBUG, "FT: SNonce mismatch in FTIE");
wpa_hexdump(MSG_DEBUG, "FT: Received SNonce",
- ftie->snonce, WPA_NONCE_LEN);
+ snonce, WPA_NONCE_LEN);
wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce",
sm->snonce, WPA_NONCE_LEN);
return -1;
@@ -467,23 +594,34 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
os_memcpy(sm->r1kh_id, parse.r1kh_id, FT_R1KH_ID_LEN);
wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID", sm->r1kh_id, FT_R1KH_ID_LEN);
wpa_hexdump(MSG_DEBUG, "FT: SNonce", sm->snonce, WPA_NONCE_LEN);
- wpa_hexdump(MSG_DEBUG, "FT: ANonce", ftie->anonce, WPA_NONCE_LEN);
- os_memcpy(sm->anonce, ftie->anonce, WPA_NONCE_LEN);
- wpa_derive_pmk_r1(sm->pmk_r0, sm->pmk_r0_name, sm->r1kh_id,
- sm->own_addr, sm->pmk_r1, sm->pmk_r1_name);
- wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", sm->pmk_r1, PMK_LEN);
+ wpa_hexdump(MSG_DEBUG, "FT: ANonce", anonce, WPA_NONCE_LEN);
+ os_memcpy(sm->anonce, anonce, WPA_NONCE_LEN);
+ if (wpa_derive_pmk_r1(sm->pmk_r0, sm->pmk_r0_len, sm->pmk_r0_name,
+ sm->r1kh_id, sm->own_addr, sm->pmk_r1,
+ sm->pmk_r1_name) < 0)
+ return -1;
+ sm->pmk_r1_len = sm->pmk_r0_len;
+ wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", sm->pmk_r1, sm->pmk_r1_len);
wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name",
sm->pmk_r1_name, WPA_PMK_NAME_LEN);
bssid = target_ap;
- if (wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, ftie->anonce,
- sm->own_addr, bssid, sm->pmk_r1_name, &sm->ptk,
- ptk_name, sm->key_mgmt, sm->pairwise_cipher) < 0)
+ if (wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len, sm->snonce,
+ anonce, sm->own_addr, bssid,
+ sm->pmk_r1_name, &sm->ptk, ptk_name, sm->key_mgmt,
+ sm->pairwise_cipher) < 0)
return -1;
- ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, ftie->anonce,
+ if (wpa_key_mgmt_fils(sm->key_mgmt)) {
+ kck = sm->ptk.kck2;
+ kck_len = sm->ptk.kck2_len;
+ } else {
+ kck = sm->ptk.kck;
+ kck_len = sm->ptk.kck_len;
+ }
+ ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, anonce,
sm->pmk_r1_name,
- sm->ptk.kck, sm->ptk.kck_len, bssid,
+ kck, kck_len, bssid,
ric_ies, ric_ies_len,
parse.mdie ? parse.mdie - 2 : NULL);
if (ft_ies) {
@@ -546,6 +684,16 @@ static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem,
int keyidx;
enum wpa_alg alg;
size_t gtk_len, keylen, rsc_len;
+ const u8 *kek;
+ size_t kek_len;
+
+ if (wpa_key_mgmt_fils(sm->key_mgmt)) {
+ kek = sm->ptk.kek2;
+ kek_len = sm->ptk.kek2_len;
+ } else {
+ kek = sm->ptk.kek;
+ kek_len = sm->ptk.kek_len;
+ }
if (gtk_elem == NULL) {
wpa_printf(MSG_DEBUG, "FT: No GTK included in FTIE");
@@ -562,8 +710,7 @@ static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem,
return -1;
}
gtk_len = gtk_elem_len - 19;
- if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, gtk_len / 8, gtk_elem + 11,
- gtk)) {
+ if (aes_unwrap(kek, kek_len, gtk_len / 8, gtk_elem + 11, gtk)) {
wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not "
"decrypt GTK");
return -1;
@@ -617,10 +764,24 @@ static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem,
static int wpa_ft_process_igtk_subelem(struct wpa_sm *sm, const u8 *igtk_elem,
size_t igtk_elem_len)
{
- u8 igtk[WPA_IGTK_LEN];
+ u8 igtk[WPA_IGTK_MAX_LEN];
+ size_t igtk_len;
u16 keyidx;
+ const u8 *kek;
+ size_t kek_len;
+
+ if (wpa_key_mgmt_fils(sm->key_mgmt)) {
+ kek = sm->ptk.kek2;
+ kek_len = sm->ptk.kek2_len;
+ } else {
+ kek = sm->ptk.kek;
+ kek_len = sm->ptk.kek_len;
+ }
- if (sm->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC)
+ if (sm->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC &&
+ sm->mgmt_group_cipher != WPA_CIPHER_BIP_GMAC_128 &&
+ sm->mgmt_group_cipher != WPA_CIPHER_BIP_GMAC_256 &&
+ sm->mgmt_group_cipher != WPA_CIPHER_BIP_CMAC_256)
return 0;
if (igtk_elem == NULL) {
@@ -631,19 +792,19 @@ static int wpa_ft_process_igtk_subelem(struct wpa_sm *sm, const u8 *igtk_elem,
wpa_hexdump_key(MSG_DEBUG, "FT: Received IGTK in Reassoc Resp",
igtk_elem, igtk_elem_len);
- if (igtk_elem_len != 2 + 6 + 1 + WPA_IGTK_LEN + 8) {
+ igtk_len = wpa_cipher_key_len(sm->mgmt_group_cipher);
+ if (igtk_elem_len != 2 + 6 + 1 + igtk_len + 8) {
wpa_printf(MSG_DEBUG, "FT: Invalid IGTK sub-elem "
"length %lu", (unsigned long) igtk_elem_len);
return -1;
}
- if (igtk_elem[8] != WPA_IGTK_LEN) {
+ if (igtk_elem[8] != igtk_len) {
wpa_printf(MSG_DEBUG, "FT: Invalid IGTK sub-elem Key Length "
"%d", igtk_elem[8]);
return -1;
}
- if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, WPA_IGTK_LEN / 8,
- igtk_elem + 9, igtk)) {
+ if (aes_unwrap(kek, kek_len, igtk_len / 8, igtk_elem + 9, igtk)) {
wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not "
"decrypt IGTK");
return -1;
@@ -654,13 +815,16 @@ static int wpa_ft_process_igtk_subelem(struct wpa_sm *sm, const u8 *igtk_elem,
keyidx = WPA_GET_LE16(igtk_elem);
wpa_hexdump_key(MSG_DEBUG, "FT: IGTK from Reassoc Resp", igtk,
- WPA_IGTK_LEN);
- if (wpa_sm_set_key(sm, WPA_ALG_IGTK, broadcast_ether_addr, keyidx, 0,
- igtk_elem + 2, 6, igtk, WPA_IGTK_LEN) < 0) {
+ igtk_len);
+ if (wpa_sm_set_key(sm, wpa_cipher_to_alg(sm->mgmt_group_cipher),
+ broadcast_ether_addr, keyidx, 0,
+ igtk_elem + 2, 6, igtk, igtk_len) < 0) {
wpa_printf(MSG_WARNING, "WPA: Failed to set IGTK to the "
"driver.");
+ os_memset(igtk, 0, sizeof(igtk));
return -1;
}
+ os_memset(igtk, 0, sizeof(igtk));
return 0;
}
@@ -672,9 +836,13 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
{
struct wpa_ft_ies parse;
struct rsn_mdie *mdie;
- struct rsn_ftie *ftie;
unsigned int count;
u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN];
+ const u8 *kck;
+ size_t kck_len;
+ int use_sha384 = wpa_key_mgmt_sha384(sm->key_mgmt);
+ const u8 *anonce, *snonce, *fte_mic;
+ u8 fte_elem_count;
wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_len);
@@ -689,7 +857,7 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
return 0;
}
- if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) {
+ if (wpa_ft_parse_ies(ies, ies_len, &parse, use_sha384) < 0) {
wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs");
return -1;
}
@@ -702,25 +870,47 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
return -1;
}
- ftie = (struct rsn_ftie *) parse.ftie;
- if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) {
- wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
- return -1;
+ if (use_sha384) {
+ struct rsn_ftie_sha384 *ftie;
+
+ ftie = (struct rsn_ftie_sha384 *) parse.ftie;
+ if (!ftie || parse.ftie_len < sizeof(*ftie)) {
+ wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
+ return -1;
+ }
+
+ anonce = ftie->anonce;
+ snonce = ftie->snonce;
+ fte_elem_count = ftie->mic_control[1];
+ fte_mic = ftie->mic;
+ } else {
+ struct rsn_ftie *ftie;
+
+ ftie = (struct rsn_ftie *) parse.ftie;
+ if (!ftie || parse.ftie_len < sizeof(*ftie)) {
+ wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
+ return -1;
+ }
+
+ anonce = ftie->anonce;
+ snonce = ftie->snonce;
+ fte_elem_count = ftie->mic_control[1];
+ fte_mic = ftie->mic;
}
- if (os_memcmp(ftie->snonce, sm->snonce, WPA_NONCE_LEN) != 0) {
+ if (os_memcmp(snonce, sm->snonce, WPA_NONCE_LEN) != 0) {
wpa_printf(MSG_DEBUG, "FT: SNonce mismatch in FTIE");
wpa_hexdump(MSG_DEBUG, "FT: Received SNonce",
- ftie->snonce, WPA_NONCE_LEN);
+ snonce, WPA_NONCE_LEN);
wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce",
sm->snonce, WPA_NONCE_LEN);
return -1;
}
- if (os_memcmp(ftie->anonce, sm->anonce, WPA_NONCE_LEN) != 0) {
+ if (os_memcmp(anonce, sm->anonce, WPA_NONCE_LEN) != 0) {
wpa_printf(MSG_DEBUG, "FT: ANonce mismatch in FTIE");
wpa_hexdump(MSG_DEBUG, "FT: Received ANonce",
- ftie->anonce, WPA_NONCE_LEN);
+ anonce, WPA_NONCE_LEN);
wpa_hexdump(MSG_DEBUG, "FT: Expected ANonce",
sm->anonce, WPA_NONCE_LEN);
return -1;
@@ -765,14 +955,22 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
count = 3;
if (parse.ric)
count += ieee802_11_ie_count(parse.ric, parse.ric_len);
- if (ftie->mic_control[1] != count) {
+ if (fte_elem_count != count) {
wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in MIC "
"Control: received %u expected %u",
- ftie->mic_control[1], count);
+ fte_elem_count, count);
return -1;
}
- if (wpa_ft_mic(sm->ptk.kck, sm->ptk.kck_len, sm->own_addr, src_addr, 6,
+ if (wpa_key_mgmt_fils(sm->key_mgmt)) {
+ kck = sm->ptk.kck2;
+ kck_len = sm->ptk.kck2_len;
+ } else {
+ kck = sm->ptk.kck;
+ kck_len = sm->ptk.kck_len;
+ }
+
+ if (wpa_ft_mic(kck, kck_len, sm->own_addr, src_addr, 6,
parse.mdie - 2, parse.mdie_len + 2,
parse.ftie - 2, parse.ftie_len + 2,
parse.rsn - 2, parse.rsn_len + 2,
@@ -782,13 +980,32 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
return -1;
}
- if (os_memcmp_const(mic, ftie->mic, 16) != 0) {
+ if (os_memcmp_const(mic, fte_mic, 16) != 0) {
wpa_printf(MSG_DEBUG, "FT: Invalid MIC in FTIE");
- wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC", ftie->mic, 16);
+ wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC", fte_mic, 16);
wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", mic, 16);
return -1;
}
+#ifdef CONFIG_OCV
+ if (wpa_sm_ocv_enabled(sm)) {
+ struct wpa_channel_info ci;
+
+ if (wpa_sm_channel_info(sm, &ci) != 0) {
+ wpa_printf(MSG_WARNING,
+ "Failed to get channel info to validate received OCI in (Re)Assoc Response");
+ return -1;
+ }
+
+ if (ocv_verify_tx_params(parse.oci, parse.oci_len, &ci,
+ channel_width_to_int(ci.chanwidth),
+ ci.seg1_idx) != 0) {
+ wpa_printf(MSG_WARNING, "%s", ocv_errorstr);
+ return -1;
+ }
+ }
+#endif /* CONFIG_OCV */
+
sm->ft_reassoc_completed = 1;
if (wpa_ft_process_gtk_subelem(sm, parse.gtk, parse.gtk_len) < 0)
diff --git a/freebsd/contrib/wpa/src/rsn_supp/wpa_i.h b/freebsd/contrib/wpa/src/rsn_supp/wpa_i.h
index 56f88dcd..0c5955c6 100644
--- a/freebsd/contrib/wpa/src/rsn_supp/wpa_i.h
+++ b/freebsd/contrib/wpa/src/rsn_supp/wpa_i.h
@@ -1,6 +1,6 @@
/*
* Internal WPA/RSN supplicant state machine definitions
- * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -11,7 +11,6 @@
#include "utils/list.h"
-struct wpa_peerkey;
struct wpa_tdls_peer;
struct wpa_eapol_key;
@@ -57,7 +56,6 @@ struct wpa_sm {
int fast_reauth; /* whether EAP fast re-authentication is enabled */
void *network_ctx;
- int peerkey_enabled;
int allowed_pairwise_cipher; /* bitfield of WPA_CIPHER_* */
int proactive_key_caching;
int eap_workaround;
@@ -88,15 +86,13 @@ struct wpa_sm {
int rsn_enabled; /* Whether RSN is enabled in configuration */
int mfp; /* 0 = disabled, 1 = optional, 2 = mandatory */
+ int ocv; /* Operating Channel Validation */
u8 *assoc_wpa_ie; /* Own WPA/RSN IE from (Re)AssocReq */
size_t assoc_wpa_ie_len;
u8 *ap_wpa_ie, *ap_rsn_ie;
size_t ap_wpa_ie_len, ap_rsn_ie_len;
-#ifdef CONFIG_PEERKEY
- struct wpa_peerkey *peerkey;
-#endif /* CONFIG_PEERKEY */
#ifdef CONFIG_TDLS
struct wpa_tdls_peer *tdls;
int tdls_prohibited;
@@ -117,18 +113,22 @@ struct wpa_sm {
#endif /* CONFIG_TDLS */
#ifdef CONFIG_IEEE80211R
- u8 xxkey[PMK_LEN]; /* PSK or the second 256 bits of MSK */
+ u8 xxkey[PMK_LEN_MAX]; /* PSK or the second 256 bits of MSK, or the
+ * first 384 bits of MSK */
size_t xxkey_len;
- u8 pmk_r0[PMK_LEN];
+ u8 pmk_r0[PMK_LEN_MAX];
+ size_t pmk_r0_len;
u8 pmk_r0_name[WPA_PMK_NAME_LEN];
- u8 pmk_r1[PMK_LEN];
+ u8 pmk_r1[PMK_LEN_MAX];
+ size_t pmk_r1_len;
u8 pmk_r1_name[WPA_PMK_NAME_LEN];
u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN];
u8 r0kh_id[FT_R0KH_ID_MAX_LEN];
size_t r0kh_id_len;
u8 r1kh_id[FT_R1KH_ID_LEN];
- int ft_completed;
- int ft_reassoc_completed;
+ unsigned int ft_completed:1;
+ unsigned int ft_reassoc_completed:1;
+ unsigned int ft_protocol:1;
int over_the_ds_in_progress;
u8 target_ap[ETH_ALEN]; /* over-the-DS target AP */
int set_ptk_after_assoc;
@@ -144,6 +144,35 @@ struct wpa_sm {
#ifdef CONFIG_TESTING_OPTIONS
struct wpabuf *test_assoc_ie;
#endif /* CONFIG_TESTING_OPTIONS */
+
+#ifdef CONFIG_FILS
+ u8 fils_nonce[FILS_NONCE_LEN];
+ u8 fils_session[FILS_SESSION_LEN];
+ u8 fils_anonce[FILS_NONCE_LEN];
+ u8 fils_key_auth_ap[FILS_MAX_KEY_AUTH_LEN];
+ u8 fils_key_auth_sta[FILS_MAX_KEY_AUTH_LEN];
+ size_t fils_key_auth_len;
+ unsigned int fils_completed:1;
+ unsigned int fils_erp_pmkid_set:1;
+ unsigned int fils_cache_id_set:1;
+ u8 fils_erp_pmkid[PMKID_LEN];
+ u8 fils_cache_id[FILS_CACHE_ID_LEN];
+ struct crypto_ecdh *fils_ecdh;
+ int fils_dh_group;
+ size_t fils_dh_elem_len;
+ struct wpabuf *fils_ft_ies;
+ u8 fils_ft[FILS_FT_MAX_LEN];
+ size_t fils_ft_len;
+#endif /* CONFIG_FILS */
+
+#ifdef CONFIG_OWE
+ struct crypto_ecdh *owe_ecdh;
+ u16 owe_group;
+#endif /* CONFIG_OWE */
+
+#ifdef CONFIG_DPP2
+ struct wpabuf *dpp_z;
+#endif /* CONFIG_DPP2 */
};
@@ -215,18 +244,23 @@ static inline u8 * wpa_sm_alloc_eapol(struct wpa_sm *sm, u8 type,
msg_len, data_pos);
}
-static inline int wpa_sm_add_pmkid(struct wpa_sm *sm, const u8 *bssid,
- const u8 *pmkid)
+static inline int wpa_sm_add_pmkid(struct wpa_sm *sm, void *network_ctx,
+ const u8 *bssid, const u8 *pmkid,
+ const u8 *cache_id, const u8 *pmk,
+ size_t pmk_len)
{
WPA_ASSERT(sm->ctx->add_pmkid);
- return sm->ctx->add_pmkid(sm->ctx->ctx, bssid, pmkid);
+ return sm->ctx->add_pmkid(sm->ctx->ctx, network_ctx, bssid, pmkid,
+ cache_id, pmk, pmk_len);
}
-static inline int wpa_sm_remove_pmkid(struct wpa_sm *sm, const u8 *bssid,
- const u8 *pmkid)
+static inline int wpa_sm_remove_pmkid(struct wpa_sm *sm, void *network_ctx,
+ const u8 *bssid, const u8 *pmkid,
+ const u8 *cache_id)
{
WPA_ASSERT(sm->ctx->remove_pmkid);
- return sm->ctx->remove_pmkid(sm->ctx->ctx, bssid, pmkid);
+ return sm->ctx->remove_pmkid(sm->ctx->ctx, network_ctx, bssid, pmkid,
+ cache_id);
}
static inline int wpa_sm_mlme_setprotection(struct wpa_sm *sm, const u8 *addr,
@@ -359,7 +393,24 @@ static inline int wpa_sm_key_mgmt_set_pmk(struct wpa_sm *sm,
return sm->ctx->key_mgmt_set_pmk(sm->ctx->ctx, pmk, pmk_len);
}
-int wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, size_t kck_len,
+static inline void wpa_sm_fils_hlp_rx(struct wpa_sm *sm,
+ const u8 *dst, const u8 *src,
+ const u8 *pkt, size_t pkt_len)
+{
+ if (sm->ctx->fils_hlp_rx)
+ sm->ctx->fils_hlp_rx(sm->ctx->ctx, dst, src, pkt, pkt_len);
+}
+
+static inline int wpa_sm_channel_info(struct wpa_sm *sm,
+ struct wpa_channel_info *ci)
+{
+ if (!sm->ctx->channel_info)
+ return -1;
+ return sm->ctx->channel_info(sm->ctx->ctx, ci);
+}
+
+
+int wpa_eapol_key_send(struct wpa_sm *sm, struct wpa_ptk *ptk,
int ver, const u8 *dest, u16 proto,
u8 *msg, size_t msg_len, u8 *key_mic);
int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
diff --git a/freebsd/contrib/wpa/src/rsn_supp/wpa_ie.c b/freebsd/contrib/wpa/src/rsn_supp/wpa_ie.c
index 4caf9c6b..6c803ece 100644
--- a/freebsd/contrib/wpa/src/rsn_supp/wpa_ie.c
+++ b/freebsd/contrib/wpa/src/rsn_supp/wpa_ie.c
@@ -2,7 +2,7 @@
/*
* wpa_supplicant - WPA/RSN IE and KDE processing
- * Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2018, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -163,6 +163,10 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len,
#ifdef CONFIG_IEEE80211R
} else if (key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X);
+#ifdef CONFIG_SHA384
+ } else if (key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X_SHA384) {
+ RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384);
+#endif /* CONFIG_SHA384 */
} else if (key_mgmt == WPA_KEY_MGMT_FT_PSK) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK);
#endif /* CONFIG_IEEE80211R */
@@ -182,6 +186,30 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len,
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192);
} else if (key_mgmt == WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B);
+#ifdef CONFIG_FILS
+ } else if (key_mgmt & WPA_KEY_MGMT_FILS_SHA256) {
+ RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FILS_SHA256);
+ } else if (key_mgmt & WPA_KEY_MGMT_FILS_SHA384) {
+ RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FILS_SHA384);
+#ifdef CONFIG_IEEE80211R
+ } else if (key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) {
+ RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA256);
+ } else if (key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) {
+ RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA384);
+#endif /* CONFIG_IEEE80211R */
+#endif /* CONFIG_FILS */
+#ifdef CONFIG_OWE
+ } else if (key_mgmt & WPA_KEY_MGMT_OWE) {
+ RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OWE);
+#endif /* CONFIG_OWE */
+#ifdef CONFIG_DPP
+ } else if (key_mgmt & WPA_KEY_MGMT_DPP) {
+ RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_DPP);
+#endif /* CONFIG_DPP */
+#ifdef CONFIG_HS20
+ } else if (key_mgmt & WPA_KEY_MGMT_OSEN) {
+ RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OSEN);
+#endif /* CONFIG_HS20 */
} else {
wpa_printf(MSG_WARNING, "Invalid key management type (%d).",
key_mgmt);
@@ -197,6 +225,8 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len,
if (sm->mfp == 2)
capab |= WPA_CAPABILITY_MFPR;
#endif /* CONFIG_IEEE80211W */
+ if (sm->ocv)
+ capab |= WPA_CAPABILITY_OCVC;
WPA_PUT_LE16(pos, capab);
pos += 2;
@@ -407,44 +437,6 @@ static int wpa_parse_generic(const u8 *pos, const u8 *end,
return 0;
}
-#ifdef CONFIG_PEERKEY
- if (pos[1] > RSN_SELECTOR_LEN + 2 &&
- RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_SMK) {
- ie->smk = pos + 2 + RSN_SELECTOR_LEN;
- ie->smk_len = pos[1] - RSN_SELECTOR_LEN;
- wpa_hexdump_key(MSG_DEBUG, "WPA: SMK in EAPOL-Key",
- pos, pos[1] + 2);
- return 0;
- }
-
- if (pos[1] > RSN_SELECTOR_LEN + 2 &&
- RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_NONCE) {
- ie->nonce = pos + 2 + RSN_SELECTOR_LEN;
- ie->nonce_len = pos[1] - RSN_SELECTOR_LEN;
- wpa_hexdump(MSG_DEBUG, "WPA: Nonce in EAPOL-Key",
- pos, pos[1] + 2);
- return 0;
- }
-
- if (pos[1] > RSN_SELECTOR_LEN + 2 &&
- RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_LIFETIME) {
- ie->lifetime = pos + 2 + RSN_SELECTOR_LEN;
- ie->lifetime_len = pos[1] - RSN_SELECTOR_LEN;
- wpa_hexdump(MSG_DEBUG, "WPA: Lifetime in EAPOL-Key",
- pos, pos[1] + 2);
- return 0;
- }
-
- if (pos[1] > RSN_SELECTOR_LEN + 2 &&
- RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_ERROR) {
- ie->error = pos + 2 + RSN_SELECTOR_LEN;
- ie->error_len = pos[1] - RSN_SELECTOR_LEN;
- wpa_hexdump(MSG_DEBUG, "WPA: Error in EAPOL-Key",
- pos, pos[1] + 2);
- return 0;
- }
-#endif /* CONFIG_PEERKEY */
-
#ifdef CONFIG_IEEE80211W
if (pos[1] > RSN_SELECTOR_LEN + 2 &&
RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) {
@@ -475,6 +467,17 @@ static int wpa_parse_generic(const u8 *pos, const u8 *end,
}
#endif /* CONFIG_P2P */
+#ifdef CONFIG_OCV
+ if (pos[1] >= RSN_SELECTOR_LEN + 1 &&
+ RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_OCI) {
+ ie->oci = pos + 2 + RSN_SELECTOR_LEN;
+ ie->oci_len = pos[1] - RSN_SELECTOR_LEN;
+ wpa_hexdump(MSG_DEBUG, "WPA: OCI KDE in EAPOL-Key",
+ pos, pos[1] + 2);
+ return 0;
+ }
+#endif /* CONFIG_OCV */
+
return 0;
}
diff --git a/freebsd/contrib/wpa/src/rsn_supp/wpa_ie.h b/freebsd/contrib/wpa/src/rsn_supp/wpa_ie.h
index fe95af0a..9d53973a 100644
--- a/freebsd/contrib/wpa/src/rsn_supp/wpa_ie.h
+++ b/freebsd/contrib/wpa/src/rsn_supp/wpa_ie.h
@@ -21,16 +21,6 @@ struct wpa_eapol_ie_parse {
size_t gtk_len;
const u8 *mac_addr;
size_t mac_addr_len;
-#ifdef CONFIG_PEERKEY
- const u8 *smk;
- size_t smk_len;
- const u8 *nonce;
- size_t nonce_len;
- const u8 *lifetime;
- size_t lifetime_len;
- const u8 *error;
- size_t error_len;
-#endif /* CONFIG_PEERKEY */
#ifdef CONFIG_IEEE80211W
const u8 *igtk;
size_t igtk_len;
@@ -63,6 +53,10 @@ struct wpa_eapol_ie_parse {
const u8 *ip_addr_req;
const u8 *ip_addr_alloc;
#endif /* CONFIG_P2P */
+#ifdef CONFIG_OCV
+ const u8 *oci;
+ size_t oci_len;
+#endif /* CONFIG_OCV */
};
int wpa_supplicant_parse_ies(const u8 *buf, size_t len,
diff --git a/freebsd/contrib/wpa/src/tls/tlsv1_client.h b/freebsd/contrib/wpa/src/tls/tlsv1_client.h
index 40fa6c7f..7fcc256f 100644
--- a/freebsd/contrib/wpa/src/tls/tlsv1_client.h
+++ b/freebsd/contrib/wpa/src/tls/tlsv1_client.h
@@ -1,6 +1,6 @@
/*
* TLS v1.0/v1.1/v1.2 client (RFC 2246, RFC 4346, RFC 5246)
- * Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2006-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -19,6 +19,7 @@ struct tlsv1_client * tlsv1_client_init(void);
void tlsv1_client_deinit(struct tlsv1_client *conn);
int tlsv1_client_established(struct tlsv1_client *conn);
int tlsv1_client_prf(struct tlsv1_client *conn, const char *label,
+ const u8 *context, size_t context_len,
int server_random_first, u8 *out, size_t out_len);
u8 * tlsv1_client_handshake(struct tlsv1_client *conn,
const u8 *in_data, size_t in_len,
diff --git a/freebsd/contrib/wpa/src/tls/tlsv1_server.h b/freebsd/contrib/wpa/src/tls/tlsv1_server.h
index 10e76993..c9c0875c 100644
--- a/freebsd/contrib/wpa/src/tls/tlsv1_server.h
+++ b/freebsd/contrib/wpa/src/tls/tlsv1_server.h
@@ -1,6 +1,6 @@
/*
* TLS v1.0/v1.1/v1.2 server (RFC 2246, RFC 4346, RFC 5246)
- * Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2006-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -19,6 +19,7 @@ struct tlsv1_server * tlsv1_server_init(struct tlsv1_credentials *cred);
void tlsv1_server_deinit(struct tlsv1_server *conn);
int tlsv1_server_established(struct tlsv1_server *conn);
int tlsv1_server_prf(struct tlsv1_server *conn, const char *label,
+ const u8 *context, size_t context_len,
int server_random_first, u8 *out, size_t out_len);
u8 * tlsv1_server_handshake(struct tlsv1_server *conn,
const u8 *in_data, size_t in_len, size_t *out_len);
@@ -48,6 +49,10 @@ void tlsv1_server_set_session_ticket_cb(struct tlsv1_server *conn,
void tlsv1_server_set_log_cb(struct tlsv1_server *conn,
void (*cb)(void *ctx, const char *msg), void *ctx);
+int tlsv1_server_get_failed(struct tlsv1_server *conn);
+int tlsv1_server_get_read_alerts(struct tlsv1_server *conn);
+int tlsv1_server_get_write_alerts(struct tlsv1_server *conn);
+
void tlsv1_server_set_test_flags(struct tlsv1_server *conn, u32 flags);
#endif /* TLSV1_SERVER_H */
diff --git a/freebsd/contrib/wpa/src/utils/base64.c b/freebsd/contrib/wpa/src/utils/base64.c
index 4127950f..a1807605 100644
--- a/freebsd/contrib/wpa/src/utils/base64.c
+++ b/freebsd/contrib/wpa/src/utils/base64.c
@@ -2,42 +2,39 @@
/*
* Base64 encoding/decoding (RFC1341)
- * Copyright (c) 2005-2011, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2005-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
+#include <stdint.h>
#include "os.h"
#include "base64.h"
static const unsigned char base64_table[65] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static const unsigned char base64_url_table[65] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
-/**
- * base64_encode - Base64 encode
- * @src: Data to be encoded
- * @len: Length of the data to be encoded
- * @out_len: Pointer to output length variable, or %NULL if not used
- * Returns: Allocated buffer of out_len bytes of encoded data,
- * or %NULL on failure
- *
- * Caller is responsible for freeing the returned buffer. Returned buffer is
- * nul terminated to make it easier to use as a C string. The nul terminator is
- * not included in out_len.
- */
-unsigned char * base64_encode(const unsigned char *src, size_t len,
- size_t *out_len)
+
+static unsigned char * base64_gen_encode(const unsigned char *src, size_t len,
+ size_t *out_len,
+ const unsigned char *table,
+ int add_pad)
{
unsigned char *out, *pos;
const unsigned char *end, *in;
size_t olen;
int line_len;
+ if (len >= SIZE_MAX / 4)
+ return NULL;
olen = len * 4 / 3 + 4; /* 3-byte blocks to 4-byte */
- olen += olen / 72; /* line feeds */
+ if (add_pad)
+ olen += olen / 72; /* line feeds */
olen++; /* nul termination */
if (olen < len)
return NULL; /* integer overflow */
@@ -50,35 +47,35 @@ unsigned char * base64_encode(const unsigned char *src, size_t len,
pos = out;
line_len = 0;
while (end - in >= 3) {
- *pos++ = base64_table[(in[0] >> 2) & 0x3f];
- *pos++ = base64_table[(((in[0] & 0x03) << 4) |
- (in[1] >> 4)) & 0x3f];
- *pos++ = base64_table[(((in[1] & 0x0f) << 2) |
- (in[2] >> 6)) & 0x3f];
- *pos++ = base64_table[in[2] & 0x3f];
+ *pos++ = table[(in[0] >> 2) & 0x3f];
+ *pos++ = table[(((in[0] & 0x03) << 4) | (in[1] >> 4)) & 0x3f];
+ *pos++ = table[(((in[1] & 0x0f) << 2) | (in[2] >> 6)) & 0x3f];
+ *pos++ = table[in[2] & 0x3f];
in += 3;
line_len += 4;
- if (line_len >= 72) {
+ if (add_pad && line_len >= 72) {
*pos++ = '\n';
line_len = 0;
}
}
if (end - in) {
- *pos++ = base64_table[(in[0] >> 2) & 0x3f];
+ *pos++ = table[(in[0] >> 2) & 0x3f];
if (end - in == 1) {
- *pos++ = base64_table[((in[0] & 0x03) << 4) & 0x3f];
- *pos++ = '=';
+ *pos++ = table[((in[0] & 0x03) << 4) & 0x3f];
+ if (add_pad)
+ *pos++ = '=';
} else {
- *pos++ = base64_table[(((in[0] & 0x03) << 4) |
- (in[1] >> 4)) & 0x3f];
- *pos++ = base64_table[((in[1] & 0x0f) << 2) & 0x3f];
+ *pos++ = table[(((in[0] & 0x03) << 4) |
+ (in[1] >> 4)) & 0x3f];
+ *pos++ = table[((in[1] & 0x0f) << 2) & 0x3f];
}
- *pos++ = '=';
+ if (add_pad)
+ *pos++ = '=';
line_len += 4;
}
- if (line_len)
+ if (add_pad && line_len)
*pos++ = '\n';
*pos = '\0';
@@ -88,26 +85,18 @@ unsigned char * base64_encode(const unsigned char *src, size_t len,
}
-/**
- * base64_decode - Base64 decode
- * @src: Data to be decoded
- * @len: Length of the data to be decoded
- * @out_len: Pointer to output length variable
- * Returns: Allocated buffer of out_len bytes of decoded data,
- * or %NULL on failure
- *
- * Caller is responsible for freeing the returned buffer.
- */
-unsigned char * base64_decode(const unsigned char *src, size_t len,
- size_t *out_len)
+static unsigned char * base64_gen_decode(const unsigned char *src, size_t len,
+ size_t *out_len,
+ const unsigned char *table)
{
unsigned char dtable[256], *out, *pos, block[4], tmp;
size_t i, count, olen;
int pad = 0;
+ size_t extra_pad;
os_memset(dtable, 0x80, 256);
for (i = 0; i < sizeof(base64_table) - 1; i++)
- dtable[base64_table[i]] = (unsigned char) i;
+ dtable[table[i]] = (unsigned char) i;
dtable['='] = 0;
count = 0;
@@ -116,21 +105,28 @@ unsigned char * base64_decode(const unsigned char *src, size_t len,
count++;
}
- if (count == 0 || count % 4)
+ if (count == 0)
return NULL;
+ extra_pad = (4 - count % 4) % 4;
- olen = count / 4 * 3;
+ olen = (count + extra_pad) / 4 * 3;
pos = out = os_malloc(olen);
if (out == NULL)
return NULL;
count = 0;
- for (i = 0; i < len; i++) {
- tmp = dtable[src[i]];
+ for (i = 0; i < len + extra_pad; i++) {
+ unsigned char val;
+
+ if (i >= len)
+ val = '=';
+ else
+ val = src[i];
+ tmp = dtable[val];
if (tmp == 0x80)
continue;
- if (src[i] == '=')
+ if (val == '=')
pad++;
block[count] = tmp;
count++;
@@ -157,3 +153,53 @@ unsigned char * base64_decode(const unsigned char *src, size_t len,
*out_len = pos - out;
return out;
}
+
+
+/**
+ * base64_encode - Base64 encode
+ * @src: Data to be encoded
+ * @len: Length of the data to be encoded
+ * @out_len: Pointer to output length variable, or %NULL if not used
+ * Returns: Allocated buffer of out_len bytes of encoded data,
+ * or %NULL on failure
+ *
+ * Caller is responsible for freeing the returned buffer. Returned buffer is
+ * nul terminated to make it easier to use as a C string. The nul terminator is
+ * not included in out_len.
+ */
+unsigned char * base64_encode(const unsigned char *src, size_t len,
+ size_t *out_len)
+{
+ return base64_gen_encode(src, len, out_len, base64_table, 1);
+}
+
+
+unsigned char * base64_url_encode(const unsigned char *src, size_t len,
+ size_t *out_len, int add_pad)
+{
+ return base64_gen_encode(src, len, out_len, base64_url_table, add_pad);
+}
+
+
+/**
+ * base64_decode - Base64 decode
+ * @src: Data to be decoded
+ * @len: Length of the data to be decoded
+ * @out_len: Pointer to output length variable
+ * Returns: Allocated buffer of out_len bytes of decoded data,
+ * or %NULL on failure
+ *
+ * Caller is responsible for freeing the returned buffer.
+ */
+unsigned char * base64_decode(const unsigned char *src, size_t len,
+ size_t *out_len)
+{
+ return base64_gen_decode(src, len, out_len, base64_table);
+}
+
+
+unsigned char * base64_url_decode(const unsigned char *src, size_t len,
+ size_t *out_len)
+{
+ return base64_gen_decode(src, len, out_len, base64_url_table);
+}
diff --git a/freebsd/contrib/wpa/src/utils/base64.h b/freebsd/contrib/wpa/src/utils/base64.h
index aa21fd0f..5a72c3eb 100644
--- a/freebsd/contrib/wpa/src/utils/base64.h
+++ b/freebsd/contrib/wpa/src/utils/base64.h
@@ -13,5 +13,9 @@ unsigned char * base64_encode(const unsigned char *src, size_t len,
size_t *out_len);
unsigned char * base64_decode(const unsigned char *src, size_t len,
size_t *out_len);
+unsigned char * base64_url_encode(const unsigned char *src, size_t len,
+ size_t *out_len, int add_pad);
+unsigned char * base64_url_decode(const unsigned char *src, size_t len,
+ size_t *out_len);
#endif /* BASE64_H */
diff --git a/freebsd/contrib/wpa/src/utils/bitfield.c b/freebsd/contrib/wpa/src/utils/bitfield.c
new file mode 100644
index 00000000..ef7b0676
--- /dev/null
+++ b/freebsd/contrib/wpa/src/utils/bitfield.c
@@ -0,0 +1,91 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Bitfield
+ * Copyright (c) 2013, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "bitfield.h"
+
+
+struct bitfield {
+ u8 *bits;
+ size_t max_bits;
+};
+
+
+struct bitfield * bitfield_alloc(size_t max_bits)
+{
+ struct bitfield *bf;
+
+ bf = os_zalloc(sizeof(*bf) + (max_bits + 7) / 8);
+ if (bf == NULL)
+ return NULL;
+ bf->bits = (u8 *) (bf + 1);
+ bf->max_bits = max_bits;
+ return bf;
+}
+
+
+void bitfield_free(struct bitfield *bf)
+{
+ os_free(bf);
+}
+
+
+void bitfield_set(struct bitfield *bf, size_t bit)
+{
+ if (bit >= bf->max_bits)
+ return;
+ bf->bits[bit / 8] |= BIT(bit % 8);
+}
+
+
+void bitfield_clear(struct bitfield *bf, size_t bit)
+{
+ if (bit >= bf->max_bits)
+ return;
+ bf->bits[bit / 8] &= ~BIT(bit % 8);
+}
+
+
+int bitfield_is_set(struct bitfield *bf, size_t bit)
+{
+ if (bit >= bf->max_bits)
+ return 0;
+ return !!(bf->bits[bit / 8] & BIT(bit % 8));
+}
+
+
+static int first_zero(u8 val)
+{
+ int i;
+ for (i = 0; i < 8; i++) {
+ if (!(val & 0x01))
+ return i;
+ val >>= 1;
+ }
+ return -1;
+}
+
+
+int bitfield_get_first_zero(struct bitfield *bf)
+{
+ size_t i;
+ for (i = 0; i < (bf->max_bits + 7) / 8; i++) {
+ if (bf->bits[i] != 0xff)
+ break;
+ }
+ if (i == (bf->max_bits + 7) / 8)
+ return -1;
+ i = i * 8 + first_zero(bf->bits[i]);
+ if (i >= bf->max_bits)
+ return -1;
+ return i;
+}
diff --git a/freebsd/contrib/wpa/src/utils/common.c b/freebsd/contrib/wpa/src/utils/common.c
index 4d414bfa..a1fdfae7 100644
--- a/freebsd/contrib/wpa/src/utils/common.c
+++ b/freebsd/contrib/wpa/src/utils/common.c
@@ -2,7 +2,7 @@
/*
* wpa_supplicant/hostapd / common helper functions, etc.
- * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -1075,7 +1075,8 @@ size_t utf8_unescape(const char *inp, size_t in_size,
in_size--;
}
- while (in_size--) {
+ while (in_size) {
+ in_size--;
if (res_size >= out_size)
return 0;
@@ -1086,8 +1087,9 @@ size_t utf8_unescape(const char *inp, size_t in_size,
return res_size;
case '\\':
- if (!in_size--)
+ if (!in_size)
return 0;
+ in_size--;
inp++;
/* fall through */
@@ -1118,7 +1120,8 @@ size_t utf8_escape(const char *inp, size_t in_size,
if (!in_size)
in_size = os_strlen(inp);
- while (in_size--) {
+ while (in_size) {
+ in_size--;
if (res_size++ >= out_size)
return 0;
@@ -1202,3 +1205,49 @@ int str_starts(const char *str, const char *start)
{
return os_strncmp(str, start, os_strlen(start)) == 0;
}
+
+
+/**
+ * rssi_to_rcpi - Convert RSSI to RCPI
+ * @rssi: RSSI to convert
+ * Returns: RCPI corresponding to the given RSSI value, or 255 if not available.
+ *
+ * It's possible to estimate RCPI based on RSSI in dBm. This calculation will
+ * not reflect the correct value for high rates, but it's good enough for Action
+ * frames which are transmitted with up to 24 Mbps rates.
+ */
+u8 rssi_to_rcpi(int rssi)
+{
+ if (!rssi)
+ return 255; /* not available */
+ if (rssi < -110)
+ return 0;
+ if (rssi > 0)
+ return 220;
+ return (rssi + 110) * 2;
+}
+
+
+char * get_param(const char *cmd, const char *param)
+{
+ const char *pos, *end;
+ char *val;
+ size_t len;
+
+ pos = os_strstr(cmd, param);
+ if (!pos)
+ return NULL;
+
+ pos += os_strlen(param);
+ end = os_strchr(pos, ' ');
+ if (end)
+ len = end - pos;
+ else
+ len = os_strlen(pos);
+ val = os_malloc(len + 1);
+ if (!val)
+ return NULL;
+ os_memcpy(val, pos, len);
+ val[len] = '\0';
+ return val;
+}
diff --git a/freebsd/contrib/wpa/src/utils/common.h b/freebsd/contrib/wpa/src/utils/common.h
index 77856774..924a8fee 100644
--- a/freebsd/contrib/wpa/src/utils/common.h
+++ b/freebsd/contrib/wpa/src/utils/common.h
@@ -17,7 +17,7 @@
#endif /* __linux__ */
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || \
- defined(__OpenBSD__)
+ defined(__OpenBSD__) || defined(__rtems__)
#include <sys/types.h>
#include <sys/endian.h>
#define __BYTE_ORDER _BYTE_ORDER
@@ -33,7 +33,8 @@
#define bswap_64 bswap64
#endif /* __OpenBSD__ */
#endif /* defined(__FreeBSD__) || defined(__NetBSD__) ||
- * defined(__DragonFly__) || defined(__OpenBSD__) */
+ * defined(__DragonFly__) || defined(__OpenBSD__) ||
+ * defined(__rtems__) */
#ifdef __APPLE__
#include <sys/types.h>
@@ -141,6 +142,7 @@ static inline unsigned int wpa_swap_32(unsigned int v)
#define host_to_le32(n) (n)
#define be_to_host32(n) wpa_swap_32(n)
#define host_to_be32(n) wpa_swap_32(n)
+#define host_to_le64(n) (n)
#define WPA_BYTE_SWAP_DEFINED
@@ -331,6 +333,9 @@ static inline void WPA_PUT_LE64(u8 *a, u64 val)
#ifndef ETH_P_RRB
#define ETH_P_RRB 0x890D
#endif /* ETH_P_RRB */
+#ifndef ETH_P_OUI
+#define ETH_P_OUI 0x88B7
+#endif /* ETH_P_OUI */
#ifdef __GNUC__
@@ -423,6 +428,7 @@ void perror(const char *s);
#define __bitwise __attribute__((bitwise))
#else
#define __force
+#undef __bitwise
#define __bitwise
#endif
@@ -552,6 +558,8 @@ int is_ctrl_char(char c);
int str_starts(const char *str, const char *start);
+u8 rssi_to_rcpi(int rssi);
+char * get_param(const char *cmd, const char *param);
/*
* gcc 4.4 ends up generating strict-aliasing warnings about some very common
diff --git a/freebsd/contrib/wpa/src/utils/const_time.h b/freebsd/contrib/wpa/src/utils/const_time.h
new file mode 100644
index 00000000..ab8f611e
--- /dev/null
+++ b/freebsd/contrib/wpa/src/utils/const_time.h
@@ -0,0 +1,191 @@
+/*
+ * Helper functions for constant time operations
+ * Copyright (c) 2019, The Linux Foundation
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ *
+ * These helper functions can be used to implement logic that needs to minimize
+ * externally visible differences in execution path by avoiding use of branches,
+ * avoiding early termination or other time differences, and forcing same memory
+ * access pattern regardless of values.
+ */
+
+#ifndef CONST_TIME_H
+#define CONST_TIME_H
+
+
+#if defined(__clang__)
+#define NO_UBSAN_UINT_OVERFLOW \
+ __attribute__((no_sanitize("unsigned-integer-overflow")))
+#else
+#define NO_UBSAN_UINT_OVERFLOW
+#endif
+
+
+/**
+ * const_time_fill_msb - Fill all bits with MSB value
+ * @val: Input value
+ * Returns: Value with all the bits set to the MSB of the input val
+ */
+static inline unsigned int const_time_fill_msb(unsigned int val)
+{
+ /* Move the MSB to LSB and multiple by -1 to fill in all bits. */
+ return (val >> (sizeof(val) * 8 - 1)) * ~0U;
+}
+
+
+/* Returns: -1 if val is zero; 0 if val is not zero */
+static inline unsigned int const_time_is_zero(unsigned int val)
+ NO_UBSAN_UINT_OVERFLOW
+{
+ /* Set MSB to 1 for 0 and fill rest of bits with the MSB value */
+ return const_time_fill_msb(~val & (val - 1));
+}
+
+
+/* Returns: -1 if a == b; 0 if a != b */
+static inline unsigned int const_time_eq(unsigned int a, unsigned int b)
+{
+ return const_time_is_zero(a ^ b);
+}
+
+
+/* Returns: -1 if a == b; 0 if a != b */
+static inline u8 const_time_eq_u8(unsigned int a, unsigned int b)
+{
+ return (u8) const_time_eq(a, b);
+}
+
+
+/**
+ * const_time_eq_bin - Constant time memory comparison
+ * @a: First buffer to compare
+ * @b: Second buffer to compare
+ * @len: Number of octets to compare
+ * Returns: -1 if buffers are equal, 0 if not
+ *
+ * This function is meant for comparing passwords or hash values where
+ * difference in execution time or memory access pattern could provide external
+ * observer information about the location of the difference in the memory
+ * buffers. The return value does not behave like memcmp(), i.e.,
+ * const_time_eq_bin() cannot be used to sort items into a defined order. Unlike
+ * memcmp(), the execution time of const_time_eq_bin() does not depend on the
+ * contents of the compared memory buffers, but only on the total compared
+ * length.
+ */
+static inline unsigned int const_time_eq_bin(const void *a, const void *b,
+ size_t len)
+{
+ const u8 *aa = a;
+ const u8 *bb = b;
+ size_t i;
+ u8 res = 0;
+
+ for (i = 0; i < len; i++)
+ res |= aa[i] ^ bb[i];
+
+ return const_time_is_zero(res);
+}
+
+
+/**
+ * const_time_select - Constant time unsigned int selection
+ * @mask: 0 (false) or -1 (true) to identify which value to select
+ * @true_val: Value to select for the true case
+ * @false_val: Value to select for the false case
+ * Returns: true_val if mask == -1, false_val if mask == 0
+ */
+static inline unsigned int const_time_select(unsigned int mask,
+ unsigned int true_val,
+ unsigned int false_val)
+{
+ return (mask & true_val) | (~mask & false_val);
+}
+
+
+/**
+ * const_time_select_int - Constant time int selection
+ * @mask: 0 (false) or -1 (true) to identify which value to select
+ * @true_val: Value to select for the true case
+ * @false_val: Value to select for the false case
+ * Returns: true_val if mask == -1, false_val if mask == 0
+ */
+static inline int const_time_select_int(unsigned int mask, int true_val,
+ int false_val)
+{
+ return (int) const_time_select(mask, (unsigned int) true_val,
+ (unsigned int) false_val);
+}
+
+
+/**
+ * const_time_select_u8 - Constant time u8 selection
+ * @mask: 0 (false) or -1 (true) to identify which value to select
+ * @true_val: Value to select for the true case
+ * @false_val: Value to select for the false case
+ * Returns: true_val if mask == -1, false_val if mask == 0
+ */
+static inline u8 const_time_select_u8(u8 mask, u8 true_val, u8 false_val)
+{
+ return (u8) const_time_select(mask, true_val, false_val);
+}
+
+
+/**
+ * const_time_select_s8 - Constant time s8 selection
+ * @mask: 0 (false) or -1 (true) to identify which value to select
+ * @true_val: Value to select for the true case
+ * @false_val: Value to select for the false case
+ * Returns: true_val if mask == -1, false_val if mask == 0
+ */
+static inline s8 const_time_select_s8(u8 mask, s8 true_val, s8 false_val)
+{
+ return (s8) const_time_select(mask, (unsigned int) true_val,
+ (unsigned int) false_val);
+}
+
+
+/**
+ * const_time_select_bin - Constant time binary buffer selection copy
+ * @mask: 0 (false) or -1 (true) to identify which value to copy
+ * @true_val: Buffer to copy for the true case
+ * @false_val: Buffer to copy for the false case
+ * @len: Number of octets to copy
+ * @dst: Destination buffer for the copy
+ *
+ * This function copies the specified buffer into the destination buffer using
+ * operations with identical memory access pattern regardless of which buffer
+ * is being copied.
+ */
+static inline void const_time_select_bin(u8 mask, const u8 *true_val,
+ const u8 *false_val, size_t len,
+ u8 *dst)
+{
+ size_t i;
+
+ for (i = 0; i < len; i++)
+ dst[i] = const_time_select_u8(mask, true_val[i], false_val[i]);
+}
+
+
+static inline int const_time_memcmp(const void *a, const void *b, size_t len)
+{
+ const u8 *aa = a;
+ const u8 *bb = b;
+ int diff, res = 0;
+ unsigned int mask;
+
+ if (len == 0)
+ return 0;
+ do {
+ len--;
+ diff = (int) aa[len] - (int) bb[len];
+ mask = const_time_is_zero((unsigned int) diff);
+ res = const_time_select_int(mask, res, diff);
+ } while (len);
+
+ return res;
+}
+
+#endif /* CONST_TIME_H */
diff --git a/freebsd/contrib/wpa/src/utils/eloop.c b/freebsd/contrib/wpa/src/utils/eloop.c
index 2ec86ff6..41de0f79 100644
--- a/freebsd/contrib/wpa/src/utils/eloop.c
+++ b/freebsd/contrib/wpa/src/utils/eloop.c
@@ -226,22 +226,25 @@ static int eloop_sock_queue(int sock, eloop_event_type type)
#ifdef CONFIG_ELOOP_KQUEUE
-static int eloop_sock_queue(int sock, eloop_event_type type)
-{
- int filter;
- struct kevent ke;
+static short event_type_kevent_filter(eloop_event_type type)
+{
switch (type) {
case EVENT_TYPE_READ:
- filter = EVFILT_READ;
- break;
+ return EVFILT_READ;
case EVENT_TYPE_WRITE:
- filter = EVFILT_WRITE;
- break;
+ return EVFILT_WRITE;
default:
- filter = 0;
+ return 0;
}
- EV_SET(&ke, sock, filter, EV_ADD, 0, 0, 0);
+}
+
+
+static int eloop_sock_queue(int sock, eloop_event_type type)
+{
+ struct kevent ke;
+
+ EV_SET(&ke, sock, event_type_kevent_filter(type), EV_ADD, 0, 0, 0);
if (kevent(eloop.kqueuefd, &ke, 1, NULL, 0, NULL) == -1) {
wpa_printf(MSG_ERROR, "%s: kevent(ADD) for fd=%d failed: %s",
__func__, sock, strerror(errno));
@@ -249,6 +252,7 @@ static int eloop_sock_queue(int sock, eloop_event_type type)
}
return 0;
}
+
#endif /* CONFIG_ELOOP_KQUEUE */
@@ -303,7 +307,7 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
#endif /* CONFIG_ELOOP_POLL */
#if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE)
if (new_max_sock >= eloop.max_fd) {
- next = eloop.max_fd == 0 ? 16 : eloop.max_fd * 2;
+ next = new_max_sock + 16;
temp_table = os_realloc_array(eloop.fd_table, next,
sizeof(struct eloop_sock));
if (temp_table == NULL)
@@ -413,7 +417,8 @@ static void eloop_sock_table_remove_sock(struct eloop_sock_table *table,
os_memset(&eloop.fd_table[sock], 0, sizeof(struct eloop_sock));
#endif /* CONFIG_ELOOP_EPOLL */
#ifdef CONFIG_ELOOP_KQUEUE
- EV_SET(&ke, sock, 0, EV_DELETE, 0, 0, 0);
+ EV_SET(&ke, sock, event_type_kevent_filter(table->type), EV_DELETE, 0,
+ 0, 0);
if (kevent(eloop.kqueuefd, &ke, 1, NULL, 0, NULL) < 0) {
wpa_printf(MSG_ERROR, "%s: kevent(DEL) for fd=%d failed: %s",
__func__, sock, strerror(errno));
diff --git a/freebsd/contrib/wpa/src/utils/eloop.h b/freebsd/contrib/wpa/src/utils/eloop.h
index 97af16f0..04ee6d18 100644
--- a/freebsd/contrib/wpa/src/utils/eloop.h
+++ b/freebsd/contrib/wpa/src/utils/eloop.h
@@ -45,16 +45,16 @@ typedef void (*eloop_sock_handler)(int sock, void *eloop_ctx, void *sock_ctx);
/**
* eloop_event_handler - eloop generic event callback type
* @eloop_ctx: Registered callback context data (eloop_data)
- * @sock_ctx: Registered callback context data (user_data)
+ * @user_ctx: Registered callback context data (user_data)
*/
-typedef void (*eloop_event_handler)(void *eloop_data, void *user_ctx);
+typedef void (*eloop_event_handler)(void *eloop_ctx, void *user_ctx);
/**
* eloop_timeout_handler - eloop timeout event callback type
* @eloop_ctx: Registered callback context data (eloop_data)
- * @sock_ctx: Registered callback context data (user_data)
+ * @user_ctx: Registered callback context data (user_data)
*/
-typedef void (*eloop_timeout_handler)(void *eloop_data, void *user_ctx);
+typedef void (*eloop_timeout_handler)(void *eloop_ctx, void *user_ctx);
/**
* eloop_signal_handler - eloop signal event callback type
diff --git a/freebsd/contrib/wpa/src/utils/list.h b/freebsd/contrib/wpa/src/utils/list.h
index ee2f4856..85aa5e39 100644
--- a/freebsd/contrib/wpa/src/utils/list.h
+++ b/freebsd/contrib/wpa/src/utils/list.h
@@ -1,6 +1,6 @@
/*
* Doubly-linked list
- * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2009-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -76,8 +76,8 @@ static inline unsigned int dl_list_len(struct dl_list *list)
dl_list_entry((list)->prev, type, member))
#define dl_list_for_each(item, list, type, member) \
- for (item = dl_list_entry((list)->next, type, member); \
- &item->member != (list); \
+ for (item = dl_list_first((list), type, member); \
+ item && item != dl_list_entry((list), type, member); \
item = dl_list_entry(item->member.next, type, member))
#define dl_list_for_each_safe(item, n, list, type, member) \
diff --git a/freebsd/contrib/wpa/src/utils/os.h b/freebsd/contrib/wpa/src/utils/os.h
index e8f0b792..21ba5c3f 100644
--- a/freebsd/contrib/wpa/src/utils/os.h
+++ b/freebsd/contrib/wpa/src/utils/os.h
@@ -614,6 +614,18 @@ size_t os_strlcpy(char *dest, const char *src, size_t siz);
*/
int os_memcmp_const(const void *a, const void *b, size_t len);
+
+/**
+ * os_memdup - Allocate duplicate of passed memory chunk
+ * @src: Source buffer to duplicate
+ * @len: Length of source buffer
+ * Returns: %NULL if allocation failed, copy of src buffer otherwise
+ *
+ * This function allocates a memory block like os_malloc() would, and
+ * copies the given source buffer into it.
+ */
+void * os_memdup(const void *src, size_t len);
+
/**
* os_exec - Execute an external program
* @program: Path to the program
diff --git a/freebsd/contrib/wpa/src/utils/os_unix.c b/freebsd/contrib/wpa/src/utils/os_unix.c
index b5879dc8..1d763968 100644
--- a/freebsd/contrib/wpa/src/utils/os_unix.c
+++ b/freebsd/contrib/wpa/src/utils/os_unix.c
@@ -2,7 +2,7 @@
/*
* OS specific functions for UNIX/POSIX systems
- * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2005-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -87,6 +87,9 @@ int os_get_reltime(struct os_reltime *t)
struct timespec ts;
int res;
+ if (TEST_FAIL())
+ return -1;
+
while (1) {
res = clock_gettime(clock_id, &ts);
if (res == 0) {
@@ -281,6 +284,13 @@ void os_daemonize_terminate(const char *pid_file)
int os_get_random(unsigned char *buf, size_t len)
{
+#ifdef TEST_FUZZ
+ size_t i;
+
+ for (i = 0; i < len; i++)
+ buf[i] = i & 0xff;
+ return 0;
+#else /* TEST_FUZZ */
FILE *f;
size_t rc;
@@ -302,6 +312,7 @@ int os_get_random(unsigned char *buf, size_t len)
return rc != len ? -1 : 0;
#endif /* __rtems__ */
+#endif /* TEST_FUZZ */
}
@@ -544,6 +555,16 @@ int os_memcmp_const(const void *a, const void *b, size_t len)
}
+void * os_memdup(const void *src, size_t len)
+{
+ void *r = os_malloc(len);
+
+ if (r && src)
+ os_memcpy(r, src, len);
+ return r;
+}
+
+
#ifdef WPA_TRACE
#if defined(WPA_TRACE_BFD) && defined(CONFIG_TESTING_OPTIONS)
@@ -576,6 +597,8 @@ static int testing_fail_alloc(void)
i++;
if (i < res && os_strcmp(func[i], "os_strdup") == 0)
i++;
+ if (i < res && os_strcmp(func[i], "os_memdup") == 0)
+ i++;
pos = wpa_trace_fail_func;
diff --git a/freebsd/contrib/wpa/src/utils/uuid.c b/freebsd/contrib/wpa/src/utils/uuid.c
index a1dedf6e..a51c0f42 100644
--- a/freebsd/contrib/wpa/src/utils/uuid.c
+++ b/freebsd/contrib/wpa/src/utils/uuid.c
@@ -11,6 +11,7 @@
#include "includes.h"
#include "common.h"
+#include "crypto/sha256.h"
#include "uuid.h"
int uuid_str2bin(const char *str, u8 *bin)
@@ -71,3 +72,27 @@ int is_nil_uuid(const u8 *uuid)
return 0;
return 1;
}
+
+
+int uuid_random(u8 *uuid)
+{
+ struct os_time t;
+ u8 hash[SHA256_MAC_LEN];
+
+ /* Use HMAC-SHA256 and timestamp as context to avoid exposing direct
+ * os_get_random() output in the UUID field. */
+ os_get_time(&t);
+ if (os_get_random(uuid, UUID_LEN) < 0 ||
+ hmac_sha256(uuid, UUID_LEN, (const u8 *) &t, sizeof(t), hash) < 0)
+ return -1;
+
+ os_memcpy(uuid, hash, UUID_LEN);
+
+ /* Version: 4 = random */
+ uuid[6] = (4 << 4) | (uuid[6] & 0x0f);
+
+ /* Variant specified in RFC 4122 */
+ uuid[8] = 0x80 | (uuid[8] & 0x3f);
+
+ return 0;
+}
diff --git a/freebsd/contrib/wpa/src/utils/uuid.h b/freebsd/contrib/wpa/src/utils/uuid.h
index 5e860cbc..6e20210f 100644
--- a/freebsd/contrib/wpa/src/utils/uuid.h
+++ b/freebsd/contrib/wpa/src/utils/uuid.h
@@ -14,5 +14,6 @@
int uuid_str2bin(const char *str, u8 *bin);
int uuid_bin2str(const u8 *bin, char *str, size_t max_len);
int is_nil_uuid(const u8 *uuid);
+int uuid_random(u8 *uuid);
#endif /* UUID_H */
diff --git a/freebsd/contrib/wpa/src/utils/wpa_debug.c b/freebsd/contrib/wpa/src/utils/wpa_debug.c
index 68100490..66596999 100644
--- a/freebsd/contrib/wpa/src/utils/wpa_debug.c
+++ b/freebsd/contrib/wpa/src/utils/wpa_debug.c
@@ -15,7 +15,7 @@
#ifdef CONFIG_DEBUG_SYSLOG
#include <syslog.h>
-static int wpa_debug_syslog = 0;
+int wpa_debug_syslog = 0;
#endif /* CONFIG_DEBUG_SYSLOG */
#ifdef CONFIG_DEBUG_LINUX_TRACING
@@ -60,6 +60,10 @@ static int wpa_to_android_level(int level)
#ifndef CONFIG_NO_STDOUT_DEBUG
#ifdef CONFIG_DEBUG_FILE
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
static FILE *out_file = NULL;
#endif /* CONFIG_DEBUG_FILE */
@@ -420,6 +424,12 @@ static void _wpa_hexdump_ascii(int level, const char *title, const void *buf,
#ifdef CONFIG_ANDROID_LOG
_wpa_hexdump(level, title, buf, len, show);
#else /* CONFIG_ANDROID_LOG */
+#ifdef CONFIG_DEBUG_SYSLOG
+ if (wpa_debug_syslog) {
+ _wpa_hexdump(level, title, buf, len, show);
+ return;
+ }
+#endif /* CONFIG_DEBUG_SYSLOG */
wpa_debug_print_timestamp();
#ifdef CONFIG_DEBUG_FILE
if (out_file) {
@@ -541,6 +551,8 @@ int wpa_debug_reopen_file(void)
int wpa_debug_open_file(const char *path)
{
#ifdef CONFIG_DEBUG_FILE
+ int out_fd;
+
if (!path)
return 0;
@@ -550,10 +562,28 @@ int wpa_debug_open_file(const char *path)
last_path = os_strdup(path);
}
- out_file = fopen(path, "a");
+ out_fd = open(path, O_CREAT | O_APPEND | O_WRONLY,
+ S_IRUSR | S_IWUSR | S_IRGRP);
+ if (out_fd < 0) {
+ wpa_printf(MSG_ERROR,
+ "%s: Failed to open output file descriptor, using standard output",
+ __func__);
+ return -1;
+ }
+
+#ifdef __linux__
+ if (fcntl(out_fd, F_SETFD, FD_CLOEXEC) < 0) {
+ wpa_printf(MSG_DEBUG,
+ "%s: Failed to set FD_CLOEXEC - continue without: %s",
+ __func__, strerror(errno));
+ }
+#endif /* __linux__ */
+
+ out_file = fdopen(out_fd, "a");
if (out_file == NULL) {
wpa_printf(MSG_ERROR, "wpa_debug_open_file: Failed to open "
"output file, using standard output");
+ close(out_fd);
return -1;
}
#ifndef _WIN32
diff --git a/freebsd/contrib/wpa/src/utils/wpa_debug.h b/freebsd/contrib/wpa/src/utils/wpa_debug.h
index 17d8f963..1fe0b7db 100644
--- a/freebsd/contrib/wpa/src/utils/wpa_debug.h
+++ b/freebsd/contrib/wpa/src/utils/wpa_debug.h
@@ -14,6 +14,9 @@
extern int wpa_debug_level;
extern int wpa_debug_show_keys;
extern int wpa_debug_timestamp;
+#ifdef CONFIG_DEBUG_SYSLOG
+extern int wpa_debug_syslog;
+#endif /* CONFIG_DEBUG_SYSLOG */
/* Debugging function - conditional printf and hex dump. Driver wrappers can
* use these for debugging purposes. */
diff --git a/freebsd/contrib/wpa/src/utils/wpabuf.c b/freebsd/contrib/wpa/src/utils/wpabuf.c
index 26e2e8bb..3959f7bc 100644
--- a/freebsd/contrib/wpa/src/utils/wpabuf.c
+++ b/freebsd/contrib/wpa/src/utils/wpabuf.c
@@ -246,15 +246,13 @@ struct wpabuf * wpabuf_concat(struct wpabuf *a, struct wpabuf *b)
if (a)
len += wpabuf_len(a);
- if (b)
- len += wpabuf_len(b);
+ len += wpabuf_len(b);
n = wpabuf_alloc(len);
if (n) {
if (a)
wpabuf_put_buf(n, a);
- if (b)
- wpabuf_put_buf(n, b);
+ wpabuf_put_buf(n, b);
}
wpabuf_free(a);
diff --git a/freebsd/contrib/wpa/src/wps/wps.c b/freebsd/contrib/wpa/src/wps/wps.c
index c0caca91..89351fe3 100644
--- a/freebsd/contrib/wpa/src/wps/wps.c
+++ b/freebsd/contrib/wpa/src/wps/wps.c
@@ -53,12 +53,11 @@ struct wps_data * wps_init(const struct wps_config *cfg)
}
if (cfg->pin) {
data->dev_pw_id = cfg->dev_pw_id;
- data->dev_password = os_malloc(cfg->pin_len);
+ data->dev_password = os_memdup(cfg->pin, cfg->pin_len);
if (data->dev_password == NULL) {
os_free(data);
return NULL;
}
- os_memcpy(data->dev_password, cfg->pin, cfg->pin_len);
data->dev_password_len = cfg->pin_len;
wpa_hexdump_key(MSG_DEBUG, "WPS: AP PIN dev_password",
data->dev_password, data->dev_password_len);
@@ -77,14 +76,12 @@ struct wps_data * wps_init(const struct wps_config *cfg)
data->dev_pw_id = cfg->wps->ap_nfc_dev_pw_id;
data->dev_password =
- os_malloc(wpabuf_len(cfg->wps->ap_nfc_dev_pw));
+ os_memdup(wpabuf_head(cfg->wps->ap_nfc_dev_pw),
+ wpabuf_len(cfg->wps->ap_nfc_dev_pw));
if (data->dev_password == NULL) {
os_free(data);
return NULL;
}
- os_memcpy(data->dev_password,
- wpabuf_head(cfg->wps->ap_nfc_dev_pw),
- wpabuf_len(cfg->wps->ap_nfc_dev_pw));
data->dev_password_len = wpabuf_len(cfg->wps->ap_nfc_dev_pw);
wpa_hexdump_key(MSG_DEBUG, "WPS: NFC dev_password",
data->dev_password, data->dev_password_len);
@@ -126,15 +123,14 @@ struct wps_data * wps_init(const struct wps_config *cfg)
if (cfg->new_ap_settings) {
data->new_ap_settings =
- os_malloc(sizeof(*data->new_ap_settings));
+ os_memdup(cfg->new_ap_settings,
+ sizeof(*data->new_ap_settings));
if (data->new_ap_settings == NULL) {
bin_clear_free(data->dev_password,
data->dev_password_len);
os_free(data);
return NULL;
}
- os_memcpy(data->new_ap_settings, cfg->new_ap_settings,
- sizeof(*data->new_ap_settings));
}
if (cfg->peer_addr)
@@ -151,6 +147,8 @@ struct wps_data * wps_init(const struct wps_config *cfg)
data->peer_pubkey_hash_set = 1;
}
+ data->multi_ap_backhaul_sta = cfg->multi_ap_backhaul_sta;
+
return data;
}
@@ -436,7 +434,7 @@ struct wpabuf * wps_build_assoc_req_ie(enum wps_request_type req_type)
if (wps_build_version(ie) ||
wps_build_req_type(ie, req_type) ||
- wps_build_wfa_ext(ie, 0, NULL, 0)) {
+ wps_build_wfa_ext(ie, 0, NULL, 0, 0)) {
wpabuf_free(ie);
return NULL;
}
@@ -470,7 +468,7 @@ struct wpabuf * wps_build_assoc_resp_ie(void)
if (wps_build_version(ie) ||
wps_build_resp_type(ie, WPS_RESP_AP) ||
- wps_build_wfa_ext(ie, 0, NULL, 0)) {
+ wps_build_wfa_ext(ie, 0, NULL, 0, 0)) {
wpabuf_free(ie);
return NULL;
}
@@ -522,7 +520,7 @@ struct wpabuf * wps_build_probe_req_ie(u16 pw_id, struct wps_device_data *dev,
wps_build_model_name(dev, ie) ||
wps_build_model_number(dev, ie) ||
wps_build_dev_name(dev, ie) ||
- wps_build_wfa_ext(ie, req_type == WPS_REQ_ENROLLEE, NULL, 0) ||
+ wps_build_wfa_ext(ie, req_type == WPS_REQ_ENROLLEE, NULL, 0, 0) ||
wps_build_req_dev_type(dev, ie, num_req_dev_types, req_dev_types)
||
wps_build_secondary_dev_type(dev, ie)
diff --git a/freebsd/contrib/wpa/src/wps/wps.h b/freebsd/contrib/wpa/src/wps/wps.h
index 2505d2d9..14ce8632 100644
--- a/freebsd/contrib/wpa/src/wps/wps.h
+++ b/freebsd/contrib/wpa/src/wps/wps.h
@@ -100,6 +100,7 @@ struct wps_device_data {
struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
int p2p;
+ u8 multi_ap_ext;
};
/**
@@ -187,6 +188,12 @@ struct wps_config {
* peer_pubkey_hash - Peer public key hash or %NULL if not known
*/
const u8 *peer_pubkey_hash;
+
+ /**
+ * multi_ap_backhaul_sta - Whether this is a Multi-AP backhaul STA
+ * enrollee
+ */
+ int multi_ap_backhaul_sta;
};
struct wps_data * wps_init(const struct wps_config *cfg);
@@ -395,6 +402,37 @@ struct wps_registrar_config {
* PSK is set for a network.
*/
int force_per_enrollee_psk;
+
+ /**
+ * multi_ap_backhaul_ssid - SSID to supply to a Multi-AP backhaul
+ * enrollee
+ *
+ * This SSID is used by the Registrar to fill in information for
+ * Credentials when the enrollee advertises it is a Multi-AP backhaul
+ * STA.
+ */
+ const u8 *multi_ap_backhaul_ssid;
+
+ /**
+ * multi_ap_backhaul_ssid_len - Length of multi_ap_backhaul_ssid in
+ * octets
+ */
+ size_t multi_ap_backhaul_ssid_len;
+
+ /**
+ * multi_ap_backhaul_network_key - The Network Key (PSK) for the
+ * Multi-AP backhaul enrollee.
+ *
+ * This key can be either the ASCII passphrase (8..63 characters) or the
+ * 32-octet PSK (64 hex characters).
+ */
+ const u8 *multi_ap_backhaul_network_key;
+
+ /**
+ * multi_ap_backhaul_network_key_len - Length of
+ * multi_ap_backhaul_network_key in octets
+ */
+ size_t multi_ap_backhaul_network_key_len;
};
diff --git a/freebsd/contrib/wpa/src/wps/wps_attr_build.c b/freebsd/contrib/wpa/src/wps/wps_attr_build.c
index e7083388..a66502f8 100644
--- a/freebsd/contrib/wpa/src/wps/wps_attr_build.c
+++ b/freebsd/contrib/wpa/src/wps/wps_attr_build.c
@@ -62,7 +62,8 @@ int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg)
}
wps->dh_privkey = wpabuf_dup(wps->wps->ap_nfc_dh_privkey);
pubkey = wpabuf_dup(wps->wps->ap_nfc_dh_pubkey);
- wps->dh_ctx = dh5_init_fixed(wps->dh_privkey, pubkey);
+ if (wps->dh_privkey && pubkey)
+ wps->dh_ctx = dh5_init_fixed(wps->dh_privkey, pubkey);
#endif /* CONFIG_WPS_NFC */
} else {
wpa_printf(MSG_DEBUG, "WPS: Generate new DH keys");
@@ -205,7 +206,8 @@ int wps_build_version(struct wpabuf *msg)
int wps_build_wfa_ext(struct wpabuf *msg, int req_to_enroll,
- const u8 *auth_macs, size_t auth_macs_count)
+ const u8 *auth_macs, size_t auth_macs_count,
+ u8 multi_ap_subelem)
{
u8 *len;
@@ -246,6 +248,14 @@ int wps_build_wfa_ext(struct wpabuf *msg, int req_to_enroll,
MAC2STR(&auth_macs[i * ETH_ALEN]));
}
+ if (multi_ap_subelem) {
+ wpa_printf(MSG_DEBUG, "WPS: * Multi-AP (0x%x)",
+ multi_ap_subelem);
+ wpabuf_put_u8(msg, WFA_ELEM_MULTI_AP);
+ wpabuf_put_u8(msg, 1); /* length */
+ wpabuf_put_u8(msg, multi_ap_subelem);
+ }
+
WPA_PUT_BE16(len, (u8 *) wpabuf_put(msg, 0) - len - 2);
#ifdef CONFIG_WPS_TESTING
diff --git a/freebsd/contrib/wpa/src/wps/wps_attr_parse.c b/freebsd/contrib/wpa/src/wps/wps_attr_parse.c
index edcfb58b..17fff46c 100644
--- a/freebsd/contrib/wpa/src/wps/wps_attr_parse.c
+++ b/freebsd/contrib/wpa/src/wps/wps_attr_parse.c
@@ -69,6 +69,17 @@ static int wps_set_vendor_ext_wfa_subelem(struct wps_parse_attr *attr,
}
attr->registrar_configuration_methods = pos;
break;
+ case WFA_ELEM_MULTI_AP:
+ if (len != 1) {
+ wpa_printf(MSG_DEBUG,
+ "WPS: Invalid Multi-AP Extension length %u",
+ len);
+ return -1;
+ }
+ attr->multi_ap_ext = *pos;
+ wpa_printf(MSG_DEBUG, "WPS: Multi-AP Extension 0x%02x",
+ attr->multi_ap_ext);
+ break;
default:
wpa_printf(MSG_MSGDUMP, "WPS: Skipped unknown WFA Vendor "
"Extension subelement %u", id);
diff --git a/freebsd/contrib/wpa/src/wps/wps_attr_parse.h b/freebsd/contrib/wpa/src/wps/wps_attr_parse.h
index 8188fe91..4de27b26 100644
--- a/freebsd/contrib/wpa/src/wps/wps_attr_parse.h
+++ b/freebsd/contrib/wpa/src/wps/wps_attr_parse.h
@@ -97,6 +97,7 @@ struct wps_parse_attr {
const u8 *cred[MAX_CRED_COUNT];
const u8 *req_dev_type[MAX_REQ_DEV_TYPE_COUNT];
const u8 *vendor_ext[MAX_WPS_PARSE_VENDOR_EXT];
+ u8 multi_ap_ext;
};
int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr);
diff --git a/freebsd/contrib/wpa/src/wps/wps_common.c b/freebsd/contrib/wpa/src/wps/wps_common.c
index d7ac00b7..a729e8e4 100644
--- a/freebsd/contrib/wpa/src/wps/wps_common.c
+++ b/freebsd/contrib/wpa/src/wps/wps_common.c
@@ -376,7 +376,7 @@ struct wpabuf * wps_get_oob_cred(struct wps_context *wps, int rf_band,
(rf_band && wps_build_rf_bands_attr(plain, rf_band)) ||
(channel && wps_build_ap_channel(plain, channel)) ||
wps_build_mac_addr(plain, wps->dev.mac_addr) ||
- wps_build_wfa_ext(plain, 0, NULL, 0)) {
+ wps_build_wfa_ext(plain, 0, NULL, 0, 0)) {
os_free(data.new_psk);
wpabuf_clear_free(plain);
return NULL;
@@ -423,7 +423,7 @@ struct wpabuf * wps_build_nfc_pw_token(u16 dev_pw_id,
if (wps_build_oob_dev_pw(data, dev_pw_id, pubkey,
wpabuf_head(dev_pw), wpabuf_len(dev_pw)) ||
- wps_build_wfa_ext(data, 0, NULL, 0)) {
+ wps_build_wfa_ext(data, 0, NULL, 0, 0)) {
wpa_printf(MSG_ERROR, "WPS: Failed to build NFC password "
"token");
wpabuf_clear_free(data);
@@ -588,7 +588,7 @@ struct wpabuf * wps_build_wsc_ack(struct wps_data *wps)
wps_build_msg_type(msg, WPS_WSC_ACK) ||
wps_build_enrollee_nonce(wps, msg) ||
wps_build_registrar_nonce(wps, msg) ||
- wps_build_wfa_ext(msg, 0, NULL, 0)) {
+ wps_build_wfa_ext(msg, 0, NULL, 0, 0)) {
wpabuf_free(msg);
return NULL;
}
@@ -612,7 +612,7 @@ struct wpabuf * wps_build_wsc_nack(struct wps_data *wps)
wps_build_enrollee_nonce(wps, msg) ||
wps_build_registrar_nonce(wps, msg) ||
wps_build_config_error(msg, wps->config_error) ||
- wps_build_wfa_ext(msg, 0, NULL, 0)) {
+ wps_build_wfa_ext(msg, 0, NULL, 0, 0)) {
wpabuf_free(msg);
return NULL;
}
@@ -656,6 +656,7 @@ int wps_nfc_gen_dh(struct wpabuf **pubkey, struct wpabuf **privkey)
pub = wpabuf_zeropad(pub, 192);
if (pub == NULL) {
wpabuf_free(priv);
+ dh5_free(dh_ctx);
return -1;
}
wpa_hexdump_buf(MSG_DEBUG, "WPS: Generated new DH pubkey", pub);
@@ -727,7 +728,7 @@ struct wpabuf * wps_build_nfc_handover_req(struct wps_context *ctx,
if (wps_build_oob_dev_pw(msg, DEV_PW_NFC_CONNECTION_HANDOVER,
nfc_dh_pubkey, NULL, 0) ||
wps_build_uuid_e(msg, ctx->uuid) ||
- wps_build_wfa_ext(msg, 0, NULL, 0)) {
+ wps_build_wfa_ext(msg, 0, NULL, 0, 0)) {
wpabuf_free(msg);
return NULL;
}
@@ -810,7 +811,7 @@ struct wpabuf * wps_build_nfc_handover_sel(struct wps_context *ctx,
wps_build_ssid(msg, ctx) ||
wps_build_ap_freq(msg, freq) ||
(bssid && wps_build_mac_addr(msg, bssid)) ||
- wps_build_wfa_ext(msg, 0, NULL, 0)) {
+ wps_build_wfa_ext(msg, 0, NULL, 0, 0)) {
wpabuf_free(msg);
return NULL;
}
@@ -849,7 +850,7 @@ struct wpabuf * wps_build_nfc_handover_req_p2p(struct wps_context *ctx,
wps_build_rf_bands(&ctx->dev, msg, 0) ||
wps_build_serial_number(&ctx->dev, msg) ||
wps_build_uuid_e(msg, ctx->uuid) ||
- wps_build_wfa_ext(msg, 0, NULL, 0)) {
+ wps_build_wfa_ext(msg, 0, NULL, 0, 0)) {
wpabuf_free(msg);
return NULL;
}
@@ -901,7 +902,7 @@ struct wpabuf * wps_build_nfc_handover_sel_p2p(struct wps_context *ctx,
wps_build_rf_bands(&ctx->dev, msg, 0) ||
wps_build_serial_number(&ctx->dev, msg) ||
wps_build_uuid_e(msg, ctx->uuid) ||
- wps_build_wfa_ext(msg, 0, NULL, 0)) {
+ wps_build_wfa_ext(msg, 0, NULL, 0, 0)) {
wpabuf_free(msg);
return NULL;
}
diff --git a/freebsd/contrib/wpa/src/wps/wps_defs.h b/freebsd/contrib/wpa/src/wps/wps_defs.h
index 301864da..9fccb4ee 100644
--- a/freebsd/contrib/wpa/src/wps/wps_defs.h
+++ b/freebsd/contrib/wpa/src/wps/wps_defs.h
@@ -152,7 +152,8 @@ enum {
WFA_ELEM_NETWORK_KEY_SHAREABLE = 0x02,
WFA_ELEM_REQUEST_TO_ENROLL = 0x03,
WFA_ELEM_SETTINGS_DELAY_TIME = 0x04,
- WFA_ELEM_REGISTRAR_CONFIGURATION_METHODS = 0x05
+ WFA_ELEM_REGISTRAR_CONFIGURATION_METHODS = 0x05,
+ WFA_ELEM_MULTI_AP = 0x06
};
/* Device Password ID */
diff --git a/freebsd/contrib/wpa/src/wps/wps_dev_attr.c b/freebsd/contrib/wpa/src/wps/wps_dev_attr.c
index 1cc6cee8..0748db70 100644
--- a/freebsd/contrib/wpa/src/wps/wps_dev_attr.c
+++ b/freebsd/contrib/wpa/src/wps/wps_dev_attr.c
@@ -392,6 +392,14 @@ int wps_process_os_version(struct wps_device_data *dev, const u8 *ver)
}
+void wps_process_vendor_ext_m1(struct wps_device_data *dev, const u8 ext)
+{
+ dev->multi_ap_ext = ext;
+ wpa_printf(MSG_DEBUG, "WPS: Multi-AP extension value %02x",
+ dev->multi_ap_ext);
+}
+
+
int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands)
{
if (bands == NULL) {
diff --git a/freebsd/contrib/wpa/src/wps/wps_dev_attr.h b/freebsd/contrib/wpa/src/wps/wps_dev_attr.h
index c9034add..a4b4173c 100644
--- a/freebsd/contrib/wpa/src/wps/wps_dev_attr.h
+++ b/freebsd/contrib/wpa/src/wps/wps_dev_attr.h
@@ -29,6 +29,7 @@ int wps_build_dev_name(struct wps_device_data *dev, struct wpabuf *msg);
int wps_process_device_attrs(struct wps_device_data *dev,
struct wps_parse_attr *attr);
int wps_process_os_version(struct wps_device_data *dev, const u8 *ver);
+void wps_process_vendor_ext_m1(struct wps_device_data *dev, const u8 ext);
int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands);
void wps_device_data_free(struct wps_device_data *dev);
int wps_build_vendor_ext(struct wps_device_data *dev, struct wpabuf *msg);
diff --git a/freebsd/contrib/wpa/src/wps/wps_enrollee.c b/freebsd/contrib/wpa/src/wps/wps_enrollee.c
index 2260b506..74cf5bc5 100644
--- a/freebsd/contrib/wpa/src/wps/wps_enrollee.c
+++ b/freebsd/contrib/wpa/src/wps/wps_enrollee.c
@@ -107,6 +107,7 @@ static struct wpabuf * wps_build_m1(struct wps_data *wps)
{
struct wpabuf *msg;
u16 config_methods;
+ u8 multi_ap_backhaul_sta = 0;
if (random_get_bytes(wps->nonce_e, WPS_NONCE_LEN) < 0)
return NULL;
@@ -136,6 +137,9 @@ static struct wpabuf * wps_build_m1(struct wps_data *wps)
WPS_CONFIG_PHY_PUSHBUTTON);
}
+ if (wps->multi_ap_backhaul_sta)
+ multi_ap_backhaul_sta = MULTI_AP_BACKHAUL_STA;
+
if (wps_build_version(msg) ||
wps_build_msg_type(msg, WPS_M1) ||
wps_build_uuid_e(msg, wps->uuid_e) ||
@@ -154,7 +158,7 @@ static struct wpabuf * wps_build_m1(struct wps_data *wps)
wps_build_dev_password_id(msg, wps->dev_pw_id) ||
wps_build_config_error(msg, WPS_CFG_NO_ERROR) ||
wps_build_os_version(&wps->wps->dev, msg) ||
- wps_build_wfa_ext(msg, 0, NULL, 0) ||
+ wps_build_wfa_ext(msg, 0, NULL, 0, multi_ap_backhaul_sta) ||
wps_build_vendor_ext_m1(&wps->wps->dev, msg)) {
wpabuf_free(msg);
return NULL;
@@ -192,7 +196,7 @@ static struct wpabuf * wps_build_m3(struct wps_data *wps)
wps_build_msg_type(msg, WPS_M3) ||
wps_build_registrar_nonce(wps, msg) ||
wps_build_e_hash(wps, msg) ||
- wps_build_wfa_ext(msg, 0, NULL, 0) ||
+ wps_build_wfa_ext(msg, 0, NULL, 0, 0) ||
wps_build_authenticator(wps, msg)) {
wpabuf_free(msg);
return NULL;
@@ -225,7 +229,7 @@ static struct wpabuf * wps_build_m5(struct wps_data *wps)
wps_build_e_snonce1(wps, plain) ||
wps_build_key_wrap_auth(wps, plain) ||
wps_build_encr_settings(wps, msg, plain) ||
- wps_build_wfa_ext(msg, 0, NULL, 0) ||
+ wps_build_wfa_ext(msg, 0, NULL, 0, 0) ||
wps_build_authenticator(wps, msg)) {
wpabuf_clear_free(plain);
wpabuf_free(msg);
@@ -395,7 +399,7 @@ static struct wpabuf * wps_build_m7(struct wps_data *wps)
(wps->wps->ap && wps_build_ap_settings(wps, plain)) ||
wps_build_key_wrap_auth(wps, plain) ||
wps_build_encr_settings(wps, msg, plain) ||
- wps_build_wfa_ext(msg, 0, NULL, 0) ||
+ wps_build_wfa_ext(msg, 0, NULL, 0, 0) ||
wps_build_authenticator(wps, msg)) {
wpabuf_clear_free(plain);
wpabuf_free(msg);
@@ -432,7 +436,7 @@ static struct wpabuf * wps_build_wsc_done(struct wps_data *wps)
wps_build_msg_type(msg, WPS_WSC_DONE) ||
wps_build_enrollee_nonce(wps, msg) ||
wps_build_registrar_nonce(wps, msg) ||
- wps_build_wfa_ext(msg, 0, NULL, 0)) {
+ wps_build_wfa_ext(msg, 0, NULL, 0, 0)) {
wpabuf_free(msg);
return NULL;
}
diff --git a/freebsd/contrib/wpa/src/wps/wps_i.h b/freebsd/contrib/wpa/src/wps/wps_i.h
index fe0c60bd..2cf22d4b 100644
--- a/freebsd/contrib/wpa/src/wps/wps_i.h
+++ b/freebsd/contrib/wpa/src/wps/wps_i.h
@@ -125,6 +125,8 @@ struct wps_data {
int pbc_in_m1;
struct wps_nfc_pw_token *nfc_pw_token;
+
+ int multi_ap_backhaul_sta;
};
@@ -163,7 +165,8 @@ int wps_build_encr_settings(struct wps_data *wps, struct wpabuf *msg,
struct wpabuf *plain);
int wps_build_version(struct wpabuf *msg);
int wps_build_wfa_ext(struct wpabuf *msg, int req_to_enroll,
- const u8 *auth_macs, size_t auth_macs_count);
+ const u8 *auth_macs, size_t auth_macs_count,
+ u8 multi_ap_subelem);
int wps_build_msg_type(struct wpabuf *msg, enum wps_msg_type msg_type);
int wps_build_enrollee_nonce(struct wps_data *wps, struct wpabuf *msg);
int wps_build_registrar_nonce(struct wps_data *wps, struct wpabuf *msg);
diff --git a/freebsd/contrib/wpa/src/wps/wps_registrar.c b/freebsd/contrib/wpa/src/wps/wps_registrar.c
index 803569ea..df30cfb4 100644
--- a/freebsd/contrib/wpa/src/wps/wps_registrar.c
+++ b/freebsd/contrib/wpa/src/wps/wps_registrar.c
@@ -190,6 +190,37 @@ struct wps_registrar {
#ifdef WPS_WORKAROUNDS
struct os_reltime pbc_ignore_start;
#endif /* WPS_WORKAROUNDS */
+
+ /**
+ * multi_ap_backhaul_ssid - SSID to supply to a Multi-AP backhaul
+ * enrollee
+ *
+ * This SSID is used by the Registrar to fill in information for
+ * Credentials when the enrollee advertises it is a Multi-AP backhaul
+ * STA.
+ */
+ u8 multi_ap_backhaul_ssid[SSID_MAX_LEN];
+
+ /**
+ * multi_ap_backhaul_ssid_len - Length of multi_ap_backhaul_ssid in
+ * octets
+ */
+ size_t multi_ap_backhaul_ssid_len;
+
+ /**
+ * multi_ap_backhaul_network_key - The Network Key (PSK) for the
+ * Multi-AP backhaul enrollee.
+ *
+ * This key can be either the ASCII passphrase (8..63 characters) or the
+ * 32-octet PSK (64 hex characters).
+ */
+ u8 *multi_ap_backhaul_network_key;
+
+ /**
+ * multi_ap_backhaul_network_key_len - Length of
+ * multi_ap_backhaul_network_key in octets
+ */
+ size_t multi_ap_backhaul_network_key_len;
};
@@ -669,6 +700,22 @@ wps_registrar_init(struct wps_context *wps,
reg->dualband = cfg->dualband;
reg->force_per_enrollee_psk = cfg->force_per_enrollee_psk;
+ if (cfg->multi_ap_backhaul_ssid) {
+ os_memcpy(reg->multi_ap_backhaul_ssid,
+ cfg->multi_ap_backhaul_ssid,
+ cfg->multi_ap_backhaul_ssid_len);
+ reg->multi_ap_backhaul_ssid_len =
+ cfg->multi_ap_backhaul_ssid_len;
+ }
+ if (cfg->multi_ap_backhaul_network_key) {
+ reg->multi_ap_backhaul_network_key =
+ os_memdup(cfg->multi_ap_backhaul_network_key,
+ cfg->multi_ap_backhaul_network_key_len);
+ if (reg->multi_ap_backhaul_network_key)
+ reg->multi_ap_backhaul_network_key_len =
+ cfg->multi_ap_backhaul_network_key_len;
+ }
+
if (wps_set_ie(reg)) {
wps_registrar_deinit(reg);
return NULL;
@@ -706,6 +753,8 @@ void wps_registrar_deinit(struct wps_registrar *reg)
eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL);
wps_registrar_flush(reg);
wpabuf_clear_free(reg->extra_cred);
+ bin_clear_free(reg->multi_ap_backhaul_network_key,
+ reg->multi_ap_backhaul_network_key_len);
os_free(reg);
}
@@ -750,12 +799,11 @@ int wps_registrar_add_pin(struct wps_registrar *reg, const u8 *addr,
p->wildcard_uuid = 1;
else
os_memcpy(p->uuid, uuid, WPS_UUID_LEN);
- p->pin = os_malloc(pin_len);
+ p->pin = os_memdup(pin, pin_len);
if (p->pin == NULL) {
os_free(p);
return -1;
}
- os_memcpy(p->pin, pin, pin_len);
p->pin_len = pin_len;
if (timeout) {
@@ -883,6 +931,7 @@ static const u8 * wps_registrar_get_pin(struct wps_registrar *reg,
const u8 *uuid, size_t *pin_len)
{
struct wps_uuid_pin *pin, *found = NULL;
+ int wildcard = 0;
wps_registrar_expire_pins(reg);
@@ -902,7 +951,7 @@ static const u8 * wps_registrar_get_pin(struct wps_registrar *reg,
pin->wildcard_uuid == 2) {
wpa_printf(MSG_DEBUG, "WPS: Found a wildcard "
"PIN. Assigned it for this UUID-E");
- pin->wildcard_uuid++;
+ wildcard = 1;
os_memcpy(pin->uuid, uuid, WPS_UUID_LEN);
found = pin;
break;
@@ -924,6 +973,8 @@ static const u8 * wps_registrar_get_pin(struct wps_registrar *reg,
}
*pin_len = found->pin_len;
found->flags |= PIN_LOCKED;
+ if (wildcard)
+ found->wildcard_uuid++;
return found->pin;
}
@@ -1281,7 +1332,7 @@ static int wps_set_ie(struct wps_registrar *reg)
wps_build_sel_reg_config_methods(reg, beacon) ||
wps_build_sel_pbc_reg_uuid_e(reg, beacon) ||
(reg->dualband && wps_build_rf_bands(&reg->wps->dev, beacon, 0)) ||
- wps_build_wfa_ext(beacon, 0, auth_macs, count) ||
+ wps_build_wfa_ext(beacon, 0, auth_macs, count, 0) ||
wps_build_vendor_ext(&reg->wps->dev, beacon)) {
wpabuf_free(beacon);
wpabuf_free(probe);
@@ -1311,7 +1362,7 @@ static int wps_set_ie(struct wps_registrar *reg)
wps_build_device_attrs(&reg->wps->dev, probe) ||
wps_build_probe_config_methods(reg, probe) ||
(reg->dualband && wps_build_rf_bands(&reg->wps->dev, probe, 0)) ||
- wps_build_wfa_ext(probe, 0, auth_macs, count) ||
+ wps_build_wfa_ext(probe, 0, auth_macs, count, 0) ||
wps_build_vendor_ext(&reg->wps->dev, probe)) {
wpabuf_free(beacon);
wpabuf_free(probe);
@@ -1406,10 +1457,9 @@ static int wps_get_dev_password(struct wps_data *wps)
return -1;
}
- wps->dev_password = os_malloc(pin_len);
+ wps->dev_password = os_memdup(pin, pin_len);
if (wps->dev_password == NULL)
return -1;
- os_memcpy(wps->dev_password, pin, pin_len);
wps->dev_password_len = pin_len;
return 0;
@@ -1593,6 +1643,7 @@ int wps_build_credential_wrap(struct wpabuf *msg,
int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
{
struct wpabuf *cred;
+ struct wps_registrar *reg = wps->wps->registrar;
if (wps->wps->registrar->skip_cred_build)
goto skip_cred_build;
@@ -1604,6 +1655,29 @@ int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
}
os_memset(&wps->cred, 0, sizeof(wps->cred));
+ if (wps->peer_dev.multi_ap_ext == MULTI_AP_BACKHAUL_STA &&
+ reg->multi_ap_backhaul_ssid_len) {
+ wpa_printf(MSG_DEBUG, "WPS: Use backhaul STA credentials");
+ os_memcpy(wps->cred.ssid, reg->multi_ap_backhaul_ssid,
+ reg->multi_ap_backhaul_ssid_len);
+ wps->cred.ssid_len = reg->multi_ap_backhaul_ssid_len;
+ /* Backhaul is always WPA2PSK */
+ wps->cred.auth_type = WPS_AUTH_WPA2PSK;
+ wps->cred.encr_type = WPS_ENCR_AES;
+ /* Set MAC address in the Credential to be the Enrollee's MAC
+ * address
+ */
+ os_memcpy(wps->cred.mac_addr, wps->mac_addr_e, ETH_ALEN);
+ if (reg->multi_ap_backhaul_network_key) {
+ os_memcpy(wps->cred.key,
+ reg->multi_ap_backhaul_network_key,
+ reg->multi_ap_backhaul_network_key_len);
+ wps->cred.key_len =
+ reg->multi_ap_backhaul_network_key_len;
+ }
+ goto use_provided;
+ }
+
os_memcpy(wps->cred.ssid, wps->wps->ssid, wps->wps->ssid_len);
wps->cred.ssid_len = wps->wps->ssid_len;
@@ -1846,7 +1920,7 @@ static struct wpabuf * wps_build_m2(struct wps_data *wps)
wps_build_config_error(msg, WPS_CFG_NO_ERROR) ||
wps_build_dev_password_id(msg, wps->dev_pw_id) ||
wps_build_os_version(&wps->wps->dev, msg) ||
- wps_build_wfa_ext(msg, 0, NULL, 0)) {
+ wps_build_wfa_ext(msg, 0, NULL, 0, 0)) {
wpabuf_free(msg);
return NULL;
}
@@ -1914,7 +1988,7 @@ static struct wpabuf * wps_build_m2d(struct wps_data *wps)
wps_build_assoc_state(wps, msg) ||
wps_build_config_error(msg, err) ||
wps_build_os_version(&wps->wps->dev, msg) ||
- wps_build_wfa_ext(msg, 0, NULL, 0)) {
+ wps_build_wfa_ext(msg, 0, NULL, 0, 0)) {
wpabuf_free(msg);
return NULL;
}
@@ -1950,7 +2024,7 @@ static struct wpabuf * wps_build_m4(struct wps_data *wps)
wps_build_r_snonce1(wps, plain) ||
wps_build_key_wrap_auth(wps, plain) ||
wps_build_encr_settings(wps, msg, plain) ||
- wps_build_wfa_ext(msg, 0, NULL, 0) ||
+ wps_build_wfa_ext(msg, 0, NULL, 0, 0) ||
wps_build_authenticator(wps, msg)) {
wpabuf_clear_free(plain);
wpabuf_free(msg);
@@ -1985,7 +2059,7 @@ static struct wpabuf * wps_build_m6(struct wps_data *wps)
wps_build_r_snonce2(wps, plain) ||
wps_build_key_wrap_auth(wps, plain) ||
wps_build_encr_settings(wps, msg, plain) ||
- wps_build_wfa_ext(msg, 0, NULL, 0) ||
+ wps_build_wfa_ext(msg, 0, NULL, 0, 0) ||
wps_build_authenticator(wps, msg)) {
wpabuf_clear_free(plain);
wpabuf_free(msg);
@@ -2022,7 +2096,7 @@ static struct wpabuf * wps_build_m8(struct wps_data *wps)
(!wps->wps->ap && !wps->er && wps_build_ap_settings(wps, plain)) ||
wps_build_key_wrap_auth(wps, plain) ||
wps_build_encr_settings(wps, msg, plain) ||
- wps_build_wfa_ext(msg, 0, NULL, 0) ||
+ wps_build_wfa_ext(msg, 0, NULL, 0, 0) ||
wps_build_authenticator(wps, msg)) {
wpabuf_clear_free(plain);
wpabuf_clear_free(msg);
@@ -2706,6 +2780,7 @@ static enum wps_process_res wps_process_m1(struct wps_data *wps,
wps->use_psk_key = 1;
}
#endif /* WPS_WORKAROUNDS */
+ wps_process_vendor_ext_m1(&wps->peer_dev, attr->multi_ap_ext);
wps->state = SEND_M2;
return WPS_CONTINUE;
diff --git a/freebsd/contrib/wpa/src/wps/wps_upnp.c b/freebsd/contrib/wpa/src/wps/wps_upnp.c
index b69d2026..71c46739 100644
--- a/freebsd/contrib/wpa/src/wps/wps_upnp.c
+++ b/freebsd/contrib/wpa/src/wps/wps_upnp.c
@@ -601,7 +601,7 @@ static struct wpabuf * build_fake_wsc_ack(void)
wpabuf_put_be16(msg, ATTR_REGISTRAR_NONCE);
wpabuf_put_be16(msg, WPS_NONCE_LEN);
wpabuf_put(msg, WPS_NONCE_LEN);
- if (wps_build_wfa_ext(msg, 0, NULL, 0)) {
+ if (wps_build_wfa_ext(msg, 0, NULL, 0, 0)) {
wpabuf_free(msg);
return NULL;
}
diff --git a/freebsd/contrib/wpa/wpa_supplicant/ap.h b/freebsd/contrib/wpa/wpa_supplicant/ap.h
index 5a59ddcc..447b5518 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/ap.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/ap.h
@@ -85,17 +85,20 @@ int wpas_ap_stop_ap(struct wpa_supplicant *wpa_s);
int wpas_ap_pmksa_cache_list(struct wpa_supplicant *wpa_s, char *buf,
size_t len);
void wpas_ap_pmksa_cache_flush(struct wpa_supplicant *wpa_s);
+int wpas_ap_pmksa_cache_list_mesh(struct wpa_supplicant *wpa_s, const u8 *addr,
+ char *buf, size_t len);
+int wpas_ap_pmksa_cache_add_external(struct wpa_supplicant *wpa_s, char *cmd);
-void wpas_event_dfs_radar_detected(struct wpa_supplicant *wpa_s,
+void wpas_ap_event_dfs_radar_detected(struct wpa_supplicant *wpa_s,
+ struct dfs_event *radar);
+void wpas_ap_event_dfs_cac_started(struct wpa_supplicant *wpa_s,
struct dfs_event *radar);
-void wpas_event_dfs_cac_started(struct wpa_supplicant *wpa_s,
- struct dfs_event *radar);
-void wpas_event_dfs_cac_finished(struct wpa_supplicant *wpa_s,
- struct dfs_event *radar);
-void wpas_event_dfs_cac_aborted(struct wpa_supplicant *wpa_s,
- struct dfs_event *radar);
-void wpas_event_dfs_cac_nop_finished(struct wpa_supplicant *wpa_s,
- struct dfs_event *radar);
+void wpas_ap_event_dfs_cac_finished(struct wpa_supplicant *wpa_s,
+ struct dfs_event *radar);
+void wpas_ap_event_dfs_cac_aborted(struct wpa_supplicant *wpa_s,
+ struct dfs_event *radar);
+void wpas_ap_event_dfs_cac_nop_finished(struct wpa_supplicant *wpa_s,
+ struct dfs_event *radar);
void ap_periodic(struct wpa_supplicant *wpa_s);
diff --git a/freebsd/contrib/wpa/wpa_supplicant/bss.c b/freebsd/contrib/wpa/wpa_supplicant/bss.c
index 4f805b1b..f9b703bb 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/bss.c
+++ b/freebsd/contrib/wpa/wpa_supplicant/bss.c
@@ -2,7 +2,7 @@
/*
* BSS table
- * Copyright (c) 2009-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2009-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -95,6 +95,7 @@ static struct wpa_bss_anqp * wpa_bss_anqp_clone(struct wpa_bss_anqp *anqp)
ANQP_DUP(nai_realm);
ANQP_DUP(anqp_3gpp);
ANQP_DUP(domain_name);
+ ANQP_DUP(fils_realm_info);
#endif /* CONFIG_INTERWORKING */
#ifdef CONFIG_HS20
ANQP_DUP(hs20_capability_list);
@@ -103,6 +104,8 @@ static struct wpa_bss_anqp * wpa_bss_anqp_clone(struct wpa_bss_anqp *anqp)
ANQP_DUP(hs20_connection_capability);
ANQP_DUP(hs20_operating_class);
ANQP_DUP(hs20_osu_providers_list);
+ ANQP_DUP(hs20_operator_icon_metadata);
+ ANQP_DUP(hs20_osu_providers_nai_list);
#endif /* CONFIG_HS20 */
#undef ANQP_DUP
@@ -170,6 +173,7 @@ static void wpa_bss_anqp_free(struct wpa_bss_anqp *anqp)
wpabuf_free(anqp->nai_realm);
wpabuf_free(anqp->anqp_3gpp);
wpabuf_free(anqp->domain_name);
+ wpabuf_free(anqp->fils_realm_info);
while ((elem = dl_list_first(&anqp->anqp_elems,
struct wpa_bss_anqp_elem, list))) {
@@ -185,6 +189,8 @@ static void wpa_bss_anqp_free(struct wpa_bss_anqp *anqp)
wpabuf_free(anqp->hs20_connection_capability);
wpabuf_free(anqp->hs20_operating_class);
wpabuf_free(anqp->hs20_osu_providers_list);
+ wpabuf_free(anqp->hs20_operator_icon_metadata);
+ wpabuf_free(anqp->hs20_osu_providers_nai_list);
#endif /* CONFIG_HS20 */
os_free(anqp);
@@ -269,9 +275,9 @@ struct wpa_bss * wpa_bss_get(struct wpa_supplicant *wpa_s, const u8 *bssid,
}
-static void calculate_update_time(const struct os_reltime *fetch_time,
- unsigned int age_ms,
- struct os_reltime *update_time)
+void calculate_update_time(const struct os_reltime *fetch_time,
+ unsigned int age_ms,
+ struct os_reltime *update_time)
{
os_time_t usec;
@@ -597,6 +603,42 @@ wpa_bss_update(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
{
u32 changes;
+ if (bss->last_update_idx == wpa_s->bss_update_idx) {
+ struct os_reltime update_time;
+
+ /*
+ * Some drivers (e.g., cfg80211) include multiple BSS entries
+ * for the same BSS if that BSS's channel changes. The BSS list
+ * implementation in wpa_supplicant does not do that and we need
+ * to filter out the obsolete results here to make sure only the
+ * most current BSS information remains in the table.
+ */
+ wpa_printf(MSG_DEBUG, "BSS: " MACSTR
+ " has multiple entries in the scan results - select the most current one",
+ MAC2STR(bss->bssid));
+ calculate_update_time(fetch_time, res->age, &update_time);
+ wpa_printf(MSG_DEBUG,
+ "Previous last_update: %u.%06u (freq %d%s)",
+ (unsigned int) bss->last_update.sec,
+ (unsigned int) bss->last_update.usec,
+ bss->freq,
+ (bss->flags & WPA_BSS_ASSOCIATED) ? " assoc" : "");
+ wpa_printf(MSG_DEBUG, "New last_update: %u.%06u (freq %d%s)",
+ (unsigned int) update_time.sec,
+ (unsigned int) update_time.usec,
+ res->freq,
+ (res->flags & WPA_SCAN_ASSOCIATED) ? " assoc" : "");
+ if ((bss->flags & WPA_BSS_ASSOCIATED) ||
+ (!(res->flags & WPA_SCAN_ASSOCIATED) &&
+ !os_reltime_before(&bss->last_update, &update_time))) {
+ wpa_printf(MSG_DEBUG,
+ "Ignore this BSS entry since the previous update looks more current");
+ return bss;
+ }
+ wpa_printf(MSG_DEBUG,
+ "Accept this BSS entry since it looks more current than the previous update");
+ }
+
changes = wpa_bss_compare_res(bss, res);
if (changes & WPA_BSS_FREQ_CHANGED_FLAG)
wpa_printf(MSG_DEBUG, "BSS: " MACSTR " changed freq %d --> %d",
@@ -1281,3 +1323,26 @@ int wpa_bss_get_bit_rates(const struct wpa_bss *bss, u8 **rates)
*rates = r;
return len;
}
+
+
+#ifdef CONFIG_FILS
+const u8 * wpa_bss_get_fils_cache_id(struct wpa_bss *bss)
+{
+ const u8 *ie;
+
+ if (bss) {
+ ie = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION);
+ if (ie && ie[1] >= 4 && WPA_GET_LE16(ie + 2) & BIT(7))
+ return ie + 4;
+ }
+
+ return NULL;
+}
+#endif /* CONFIG_FILS */
+
+
+int wpa_bss_ext_capab(const struct wpa_bss *bss, unsigned int capab)
+{
+ return ieee802_11_ext_capab(wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB),
+ capab);
+}
diff --git a/freebsd/contrib/wpa/wpa_supplicant/bss.h b/freebsd/contrib/wpa/wpa_supplicant/bss.h
index 84e8fb07..3ce8cd3f 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/bss.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/bss.h
@@ -1,6 +1,6 @@
/*
* BSS table
- * Copyright (c) 2009-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2009-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -40,6 +40,7 @@ struct wpa_bss_anqp {
struct wpabuf *nai_realm;
struct wpabuf *anqp_3gpp;
struct wpabuf *domain_name;
+ struct wpabuf *fils_realm_info;
struct dl_list anqp_elems; /* list of struct wpa_bss_anqp_elem */
#endif /* CONFIG_INTERWORKING */
#ifdef CONFIG_HS20
@@ -49,6 +50,8 @@ struct wpa_bss_anqp {
struct wpabuf *hs20_connection_capability;
struct wpabuf *hs20_operating_class;
struct wpabuf *hs20_osu_providers_list;
+ struct wpabuf *hs20_operator_icon_metadata;
+ struct wpabuf *hs20_osu_providers_nai_list;
#endif /* CONFIG_HS20 */
};
@@ -144,6 +147,8 @@ int wpa_bss_get_max_rate(const struct wpa_bss *bss);
int wpa_bss_get_bit_rates(const struct wpa_bss *bss, u8 **rates);
struct wpa_bss_anqp * wpa_bss_anqp_alloc(void);
int wpa_bss_anqp_unshare_alloc(struct wpa_bss *bss);
+const u8 * wpa_bss_get_fils_cache_id(struct wpa_bss *bss);
+int wpa_bss_ext_capab(const struct wpa_bss *bss, unsigned int capab);
static inline int bss_is_dmg(const struct wpa_bss *bss)
{
@@ -167,4 +172,8 @@ static inline void wpa_bss_update_level(struct wpa_bss *bss, int new_level)
bss->level = new_level;
}
+void calculate_update_time(const struct os_reltime *fetch_time,
+ unsigned int age_ms,
+ struct os_reltime *update_time);
+
#endif /* BSS_H */
diff --git a/freebsd/contrib/wpa/wpa_supplicant/config.c b/freebsd/contrib/wpa/wpa_supplicant/config.c
index cf9da641..0eac7a9e 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/config.c
+++ b/freebsd/contrib/wpa/wpa_supplicant/config.c
@@ -2,7 +2,7 @@
/*
* WPA Supplicant / Configuration parser and common functions
- * Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2018, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -13,6 +13,7 @@
#include "common.h"
#include "utils/uuid.h"
#include "utils/ip_addr.h"
+#include "common/ieee802_1x_defs.h"
#include "crypto/sha1.h"
#include "rsn_supp/wpa.h"
#include "eap_peer/eap.h"
@@ -398,6 +399,50 @@ static char * wpa_config_write_bssid(const struct parse_data *data,
#endif /* NO_CONFIG_WRITE */
+static int wpa_config_parse_bssid_hint(const struct parse_data *data,
+ struct wpa_ssid *ssid, int line,
+ const char *value)
+{
+ if (value[0] == '\0' || os_strcmp(value, "\"\"") == 0 ||
+ os_strcmp(value, "any") == 0) {
+ ssid->bssid_hint_set = 0;
+ wpa_printf(MSG_MSGDUMP, "BSSID hint any");
+ return 0;
+ }
+ if (hwaddr_aton(value, ssid->bssid_hint)) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid BSSID hint '%s'.",
+ line, value);
+ return -1;
+ }
+ ssid->bssid_hint_set = 1;
+ wpa_hexdump(MSG_MSGDUMP, "BSSID hint", ssid->bssid_hint, ETH_ALEN);
+ return 0;
+}
+
+
+#ifndef NO_CONFIG_WRITE
+static char * wpa_config_write_bssid_hint(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ char *value;
+ int res;
+
+ if (!ssid->bssid_hint_set)
+ return NULL;
+
+ value = os_malloc(20);
+ if (!value)
+ return NULL;
+ res = os_snprintf(value, 20, MACSTR, MAC2STR(ssid->bssid_hint));
+ if (os_snprintf_error(20, res)) {
+ os_free(value);
+ return NULL;
+ }
+ return value;
+}
+#endif /* NO_CONFIG_WRITE */
+
+
static int wpa_config_parse_bssid_blacklist(const struct parse_data *data,
struct wpa_ssid *ssid, int line,
const char *value)
@@ -692,6 +737,10 @@ static int wpa_config_parse_key_mgmt(const struct parse_data *data,
val |= WPA_KEY_MGMT_FT_PSK;
else if (os_strcmp(start, "FT-EAP") == 0)
val |= WPA_KEY_MGMT_FT_IEEE8021X;
+#ifdef CONFIG_SHA384
+ else if (os_strcmp(start, "FT-EAP-SHA384") == 0)
+ val |= WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
+#endif /* CONFIG_SHA384 */
#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_IEEE80211W
else if (os_strcmp(start, "WPA-PSK-SHA256") == 0)
@@ -721,6 +770,26 @@ static int wpa_config_parse_key_mgmt(const struct parse_data *data,
else if (os_strcmp(start, "WPA-EAP-SUITE-B-192") == 0)
val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
#endif /* CONFIG_SUITEB192 */
+#ifdef CONFIG_FILS
+ else if (os_strcmp(start, "FILS-SHA256") == 0)
+ val |= WPA_KEY_MGMT_FILS_SHA256;
+ else if (os_strcmp(start, "FILS-SHA384") == 0)
+ val |= WPA_KEY_MGMT_FILS_SHA384;
+#ifdef CONFIG_IEEE80211R
+ else if (os_strcmp(start, "FT-FILS-SHA256") == 0)
+ val |= WPA_KEY_MGMT_FT_FILS_SHA256;
+ else if (os_strcmp(start, "FT-FILS-SHA384") == 0)
+ val |= WPA_KEY_MGMT_FT_FILS_SHA384;
+#endif /* CONFIG_IEEE80211R */
+#endif /* CONFIG_FILS */
+#ifdef CONFIG_OWE
+ else if (os_strcmp(start, "OWE") == 0)
+ val |= WPA_KEY_MGMT_OWE;
+#endif /* CONFIG_OWE */
+#ifdef CONFIG_DPP
+ else if (os_strcmp(start, "DPP") == 0)
+ val |= WPA_KEY_MGMT_DPP;
+#endif /* CONFIG_DPP */
else {
wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
line, start);
@@ -829,6 +898,18 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data,
}
pos += ret;
}
+
+#ifdef CONFIG_SHA384
+ if (ssid->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) {
+ ret = os_snprintf(pos, end - pos, "%sFT-EAP-SHA384",
+ pos == buf ? "" : " ");
+ if (os_snprintf_error(end - pos, ret)) {
+ end[-1] = '\0';
+ return buf;
+ }
+ pos += ret;
+ }
+#endif /* CONFIG_SHA384 */
#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_IEEE80211W
@@ -923,6 +1004,71 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data,
}
#endif /* CONFIG_SUITEB192 */
+#ifdef CONFIG_FILS
+ if (ssid->key_mgmt & WPA_KEY_MGMT_FILS_SHA256) {
+ ret = os_snprintf(pos, end - pos, "%sFILS-SHA256",
+ pos == buf ? "" : " ");
+ if (os_snprintf_error(end - pos, ret)) {
+ end[-1] = '\0';
+ return buf;
+ }
+ pos += ret;
+ }
+ if (ssid->key_mgmt & WPA_KEY_MGMT_FILS_SHA384) {
+ ret = os_snprintf(pos, end - pos, "%sFILS-SHA384",
+ pos == buf ? "" : " ");
+ if (os_snprintf_error(end - pos, ret)) {
+ end[-1] = '\0';
+ return buf;
+ }
+ pos += ret;
+ }
+#ifdef CONFIG_IEEE80211R
+ if (ssid->key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) {
+ ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA256",
+ pos == buf ? "" : " ");
+ if (os_snprintf_error(end - pos, ret)) {
+ end[-1] = '\0';
+ return buf;
+ }
+ pos += ret;
+ }
+ if (ssid->key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) {
+ ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA384",
+ pos == buf ? "" : " ");
+ if (os_snprintf_error(end - pos, ret)) {
+ end[-1] = '\0';
+ return buf;
+ }
+ pos += ret;
+ }
+#endif /* CONFIG_IEEE80211R */
+#endif /* CONFIG_FILS */
+
+#ifdef CONFIG_DPP
+ if (ssid->key_mgmt & WPA_KEY_MGMT_DPP) {
+ ret = os_snprintf(pos, end - pos, "%sDPP",
+ pos == buf ? "" : " ");
+ if (os_snprintf_error(end - pos, ret)) {
+ end[-1] = '\0';
+ return buf;
+ }
+ pos += ret;
+ }
+#endif /* CONFIG_DPP */
+
+#ifdef CONFIG_OWE
+ if (ssid->key_mgmt & WPA_KEY_MGMT_OWE) {
+ ret = os_snprintf(pos, end - pos, "%sOWE",
+ pos == buf ? "" : " ");
+ if (os_snprintf_error(end - pos, ret)) {
+ end[-1] = '\0';
+ return buf;
+ }
+ pos += ret;
+ }
+#endif /* CONFIG_OWE */
+
if (pos == buf) {
os_free(buf);
buf = NULL;
@@ -1044,6 +1190,40 @@ static char * wpa_config_write_group(const struct parse_data *data,
#endif /* NO_CONFIG_WRITE */
+static int wpa_config_parse_group_mgmt(const struct parse_data *data,
+ struct wpa_ssid *ssid, int line,
+ const char *value)
+{
+ int val;
+
+ val = wpa_config_parse_cipher(line, value);
+ if (val == -1)
+ return -1;
+
+ if (val & ~WPA_ALLOWED_GROUP_MGMT_CIPHERS) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: not allowed group management cipher (0x%x).",
+ line, val);
+ return -1;
+ }
+
+ if (ssid->group_mgmt_cipher == val)
+ return 1;
+ wpa_printf(MSG_MSGDUMP, "group_mgmt: 0x%x", val);
+ ssid->group_mgmt_cipher = val;
+ return 0;
+}
+
+
+#ifndef NO_CONFIG_WRITE
+static char * wpa_config_write_group_mgmt(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ return wpa_config_write_cipher(ssid->group_mgmt_cipher);
+}
+#endif /* NO_CONFIG_WRITE */
+
+
static int wpa_config_parse_auth_alg(const struct parse_data *data,
struct wpa_ssid *ssid, int line,
const char *value)
@@ -1818,6 +1998,140 @@ static char * wpa_config_write_mesh_basic_rates(const struct parse_data *data,
#endif /* CONFIG_MESH */
+#ifdef CONFIG_MACSEC
+
+static int wpa_config_parse_mka_cak(const struct parse_data *data,
+ struct wpa_ssid *ssid, int line,
+ const char *value)
+{
+ size_t len;
+
+ len = os_strlen(value);
+ if (len > 2 * MACSEC_CAK_MAX_LEN ||
+ (len != 2 * 16 && len != 2 * 32) ||
+ hexstr2bin(value, ssid->mka_cak, len / 2)) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid MKA-CAK '%s'.",
+ line, value);
+ return -1;
+ }
+ ssid->mka_cak_len = len / 2;
+ ssid->mka_psk_set |= MKA_PSK_SET_CAK;
+
+ wpa_hexdump_key(MSG_MSGDUMP, "MKA-CAK", ssid->mka_cak,
+ ssid->mka_cak_len);
+ return 0;
+}
+
+
+static int wpa_config_parse_mka_ckn(const struct parse_data *data,
+ struct wpa_ssid *ssid, int line,
+ const char *value)
+{
+ size_t len;
+
+ len = os_strlen(value);
+ if (len > 2 * MACSEC_CKN_MAX_LEN || /* too long */
+ len < 2 || /* too short */
+ len % 2 != 0 /* not an integral number of bytes */) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid MKA-CKN '%s'.",
+ line, value);
+ return -1;
+ }
+ ssid->mka_ckn_len = len / 2;
+ if (hexstr2bin(value, ssid->mka_ckn, ssid->mka_ckn_len)) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid MKA-CKN '%s'.",
+ line, value);
+ return -1;
+ }
+
+ ssid->mka_psk_set |= MKA_PSK_SET_CKN;
+
+ wpa_hexdump_key(MSG_MSGDUMP, "MKA-CKN", ssid->mka_ckn,
+ ssid->mka_ckn_len);
+ return 0;
+}
+
+
+#ifndef NO_CONFIG_WRITE
+
+static char * wpa_config_write_mka_cak(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ if (!(ssid->mka_psk_set & MKA_PSK_SET_CAK))
+ return NULL;
+
+ return wpa_config_write_string_hex(ssid->mka_cak, ssid->mka_cak_len);
+}
+
+
+static char * wpa_config_write_mka_ckn(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ if (!(ssid->mka_psk_set & MKA_PSK_SET_CKN))
+ return NULL;
+ return wpa_config_write_string_hex(ssid->mka_ckn, ssid->mka_ckn_len);
+}
+
+#endif /* NO_CONFIG_WRITE */
+
+#endif /* CONFIG_MACSEC */
+
+
+#ifdef CONFIG_OCV
+
+static int wpa_config_parse_ocv(const struct parse_data *data,
+ struct wpa_ssid *ssid, int line,
+ const char *value)
+{
+ char *end;
+
+ ssid->ocv = strtol(value, &end, 0);
+ if (*end || ssid->ocv < 0 || ssid->ocv > 1) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid ocv value '%s'.",
+ line, value);
+ return -1;
+ }
+ if (ssid->ocv && ssid->ieee80211w == NO_MGMT_FRAME_PROTECTION)
+ ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
+ return 0;
+}
+
+
+#ifndef NO_CONFIG_WRITE
+static char * wpa_config_write_ocv(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ char *value = os_malloc(20);
+
+ if (!value)
+ return NULL;
+ os_snprintf(value, 20, "%d", ssid->ocv);
+ value[20 - 1] = '\0';
+ return value;
+}
+#endif /* NO_CONFIG_WRITE */
+
+#endif /* CONFIG_OCV */
+
+
+static int wpa_config_parse_peerkey(const struct parse_data *data,
+ struct wpa_ssid *ssid, int line,
+ const char *value)
+{
+ wpa_printf(MSG_INFO, "NOTE: Obsolete peerkey parameter ignored");
+ return 0;
+}
+
+
+#ifndef NO_CONFIG_WRITE
+static char * wpa_config_write_peerkey(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ return NULL;
+}
+#endif /* NO_CONFIG_WRITE */
+
+
/* Helper macros for network block parser */
#ifdef OFFSET
@@ -1909,24 +2223,34 @@ static const struct parse_data ssid_fields[] = {
{ STR_RANGE(ssid, 0, SSID_MAX_LEN) },
{ INT_RANGE(scan_ssid, 0, 1) },
{ FUNC(bssid) },
+ { FUNC(bssid_hint) },
{ FUNC(bssid_blacklist) },
{ FUNC(bssid_whitelist) },
{ FUNC_KEY(psk) },
{ INT(mem_only_psk) },
+ { STR_KEY(sae_password) },
+ { STR(sae_password_id) },
{ FUNC(proto) },
{ FUNC(key_mgmt) },
{ INT(bg_scan_period) },
{ FUNC(pairwise) },
{ FUNC(group) },
+ { FUNC(group_mgmt) },
{ FUNC(auth_alg) },
{ FUNC(scan_freq) },
{ FUNC(freq_list) },
+ { INT_RANGE(ht, 0, 1) },
+ { INT_RANGE(vht, 0, 1) },
+ { INT_RANGE(ht40, -1, 1) },
{ INT_RANGE(max_oper_chwidth, VHT_CHANWIDTH_USE_HT,
VHT_CHANWIDTH_80P80MHZ) },
+ { INT(vht_center_freq1) },
+ { INT(vht_center_freq2) },
#ifdef IEEE8021X_EAPOL
{ FUNC(eap) },
{ STR_LENe(identity) },
{ STR_LENe(anonymous_identity) },
+ { STR_LENe(imsi_identity) },
{ FUNC_KEY(password) },
{ STRe(ca_cert) },
{ STRe(ca_path) },
@@ -1935,6 +2259,7 @@ static const struct parse_data ssid_fields[] = {
{ STR_KEYe(private_key_passwd) },
{ STRe(dh_file) },
{ STRe(subject_match) },
+ { STRe(check_cert_subject) },
{ STRe(altsubject_match) },
{ STRe(domain_suffix_match) },
{ STRe(domain_match) },
@@ -1945,6 +2270,7 @@ static const struct parse_data ssid_fields[] = {
{ STR_KEYe(private_key2_passwd) },
{ STRe(dh_file2) },
{ STRe(subject_match2) },
+ { STRe(check_cert_subject2) },
{ STRe(altsubject_match2) },
{ STRe(domain_suffix_match2) },
{ STRe(domain_match2) },
@@ -1983,6 +2309,7 @@ static const struct parse_data ssid_fields[] = {
#ifdef CONFIG_MESH
{ INT_RANGE(mode, 0, 5) },
{ INT_RANGE(no_auto_peer, 0, 1) },
+ { INT_RANGE(mesh_rssi_threshold, -255, 1) },
#else /* CONFIG_MESH */
{ INT_RANGE(mode, 0, 4) },
#endif /* CONFIG_MESH */
@@ -1992,7 +2319,10 @@ static const struct parse_data ssid_fields[] = {
#ifdef CONFIG_IEEE80211W
{ INT_RANGE(ieee80211w, 0, 2) },
#endif /* CONFIG_IEEE80211W */
- { INT_RANGE(peerkey, 0, 1) },
+#ifdef CONFIG_OCV
+ { FUNC(ocv) },
+#endif /* CONFIG_OCV */
+ { FUNC(peerkey) /* obsolete - removed */ },
{ INT_RANGE(mixed_cell, 0, 1) },
{ INT_RANGE(frequency, 0, 65000) },
{ INT_RANGE(fixed_freq, 0, 1) },
@@ -2021,6 +2351,8 @@ static const struct parse_data ssid_fields[] = {
{ INT_RANGE(disable_sgi, 0, 1) },
{ INT_RANGE(disable_ldpc, 0, 1) },
{ INT_RANGE(ht40_intolerant, 0, 1) },
+ { INT_RANGE(tx_stbc, -1, 1) },
+ { INT_RANGE(rx_stbc, -1, 3) },
{ INT_RANGE(disable_max_amsdu, -1, 1) },
{ INT_RANGE(ampdu_factor, -1, 3) },
{ INT_RANGE(ampdu_density, -1, 7) },
@@ -2052,13 +2384,31 @@ static const struct parse_data ssid_fields[] = {
{ INT(beacon_int) },
#ifdef CONFIG_MACSEC
{ INT_RANGE(macsec_policy, 0, 1) },
+ { INT_RANGE(macsec_integ_only, 0, 1) },
+ { INT_RANGE(macsec_replay_protect, 0, 1) },
+ { INT(macsec_replay_window) },
+ { INT_RANGE(macsec_port, 1, 65534) },
+ { INT_RANGE(mka_priority, 0, 255) },
+ { FUNC_KEY(mka_cak) },
+ { FUNC_KEY(mka_ckn) },
#endif /* CONFIG_MACSEC */
#ifdef CONFIG_HS20
{ INT(update_identifier) },
+ { STR_RANGE(roaming_consortium_selection, 0, MAX_ROAMING_CONS_OI_LEN) },
#endif /* CONFIG_HS20 */
{ INT_RANGE(mac_addr, 0, 2) },
{ INT_RANGE(pbss, 0, 2) },
{ INT_RANGE(wps_disabled, 0, 1) },
+ { INT_RANGE(fils_dh_group, 0, 65535) },
+#ifdef CONFIG_DPP
+ { STR(dpp_connector) },
+ { STR_LEN(dpp_netaccesskey) },
+ { INT(dpp_netaccesskey_expiry) },
+ { STR_LEN(dpp_csign) },
+#endif /* CONFIG_DPP */
+ { INT_RANGE(owe_group, 0, 65535) },
+ { INT_RANGE(owe_only, 0, 1) },
+ { INT_RANGE(multi_ap_backhaul_sta, 0, 1) },
};
#undef OFFSET
@@ -2170,6 +2520,7 @@ static void eap_peer_config_free(struct eap_peer_config *eap)
os_free(eap->eap_methods);
bin_clear_free(eap->identity, eap->identity_len);
os_free(eap->anonymous_identity);
+ os_free(eap->imsi_identity);
bin_clear_free(eap->password, eap->password_len);
os_free(eap->ca_cert);
os_free(eap->ca_path);
@@ -2178,6 +2529,7 @@ static void eap_peer_config_free(struct eap_peer_config *eap)
str_clear_free(eap->private_key_passwd);
os_free(eap->dh_file);
os_free(eap->subject_match);
+ os_free(eap->check_cert_subject);
os_free(eap->altsubject_match);
os_free(eap->domain_suffix_match);
os_free(eap->domain_match);
@@ -2188,6 +2540,7 @@ static void eap_peer_config_free(struct eap_peer_config *eap)
str_clear_free(eap->private_key2_passwd);
os_free(eap->dh_file2);
os_free(eap->subject_match2);
+ os_free(eap->check_cert_subject2);
os_free(eap->altsubject_match2);
os_free(eap->domain_suffix_match2);
os_free(eap->domain_match2);
@@ -2228,6 +2581,8 @@ void wpa_config_free_ssid(struct wpa_ssid *ssid)
os_free(ssid->ssid);
str_clear_free(ssid->passphrase);
os_free(ssid->ext_psk);
+ str_clear_free(ssid->sae_password);
+ os_free(ssid->sae_password_id);
#ifdef IEEE8021X_EAPOL
eap_peer_config_free(&ssid->eap);
#endif /* IEEE8021X_EAPOL */
@@ -2244,6 +2599,12 @@ void wpa_config_free_ssid(struct wpa_ssid *ssid)
#ifdef CONFIG_MESH
os_free(ssid->mesh_basic_rates);
#endif /* CONFIG_MESH */
+#ifdef CONFIG_HS20
+ os_free(ssid->roaming_consortium_selection);
+#endif /* CONFIG_HS20 */
+ os_free(ssid->dpp_connector);
+ bin_clear_free(ssid->dpp_netaccesskey, ssid->dpp_netaccesskey_len);
+ os_free(ssid->dpp_csign);
while ((psk = dl_list_first(&ssid->psk_list, struct psk_list_entry,
list))) {
dl_list_del(&psk->list);
@@ -2497,6 +2858,7 @@ void wpa_config_set_network_defaults(struct wpa_ssid *ssid)
ssid->group_cipher = DEFAULT_GROUP;
ssid->key_mgmt = DEFAULT_KEY_MGMT;
ssid->bg_scan_period = DEFAULT_BG_SCAN_PERIOD;
+ ssid->ht = 1;
#ifdef IEEE8021X_EAPOL
ssid->eapol_flags = DEFAULT_EAPOL_FLAGS;
ssid->eap_workaround = DEFAULT_EAP_WORKAROUND;
@@ -2508,12 +2870,15 @@ void wpa_config_set_network_defaults(struct wpa_ssid *ssid)
ssid->dot11MeshRetryTimeout = DEFAULT_MESH_RETRY_TIMEOUT;
ssid->dot11MeshConfirmTimeout = DEFAULT_MESH_CONFIRM_TIMEOUT;
ssid->dot11MeshHoldingTimeout = DEFAULT_MESH_HOLDING_TIMEOUT;
+ ssid->mesh_rssi_threshold = DEFAULT_MESH_RSSI_THRESHOLD;
#endif /* CONFIG_MESH */
#ifdef CONFIG_HT_OVERRIDES
ssid->disable_ht = DEFAULT_DISABLE_HT;
ssid->disable_ht40 = DEFAULT_DISABLE_HT40;
ssid->disable_sgi = DEFAULT_DISABLE_SGI;
ssid->disable_ldpc = DEFAULT_DISABLE_LDPC;
+ ssid->tx_stbc = DEFAULT_TX_STBC;
+ ssid->rx_stbc = DEFAULT_RX_STBC;
ssid->disable_max_amsdu = DEFAULT_DISABLE_MAX_AMSDU;
ssid->ampdu_factor = DEFAULT_AMPDU_FACTOR;
ssid->ampdu_density = DEFAULT_AMPDU_DENSITY;
@@ -2540,7 +2905,11 @@ void wpa_config_set_network_defaults(struct wpa_ssid *ssid)
#ifdef CONFIG_IEEE80211W
ssid->ieee80211w = MGMT_FRAME_PROTECTION_DEFAULT;
#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_MACSEC
+ ssid->mka_priority = DEFAULT_PRIO_NOT_KEY_SERVER;
+#endif /* CONFIG_MACSEC */
ssid->mac_addr = -1;
+ ssid->max_oper_chwidth = DEFAULT_MAX_OPER_CHWIDTH;
}
@@ -2851,11 +3220,64 @@ static int wpa_config_set_cred_req_conn_capab(struct wpa_cred *cred,
}
+static int wpa_config_set_cred_roaming_consortiums(struct wpa_cred *cred,
+ const char *value)
+{
+ u8 roaming_consortiums[MAX_ROAMING_CONS][MAX_ROAMING_CONS_OI_LEN];
+ size_t roaming_consortiums_len[MAX_ROAMING_CONS];
+ unsigned int num_roaming_consortiums = 0;
+ const char *pos, *end;
+ size_t len;
+
+ os_memset(roaming_consortiums, 0, sizeof(roaming_consortiums));
+ os_memset(roaming_consortiums_len, 0, sizeof(roaming_consortiums_len));
+
+ for (pos = value;;) {
+ end = os_strchr(pos, ',');
+ len = end ? (size_t) (end - pos) : os_strlen(pos);
+ if (!end && len == 0)
+ break;
+ if (len == 0 || (len & 1) != 0 ||
+ len / 2 > MAX_ROAMING_CONS_OI_LEN ||
+ hexstr2bin(pos,
+ roaming_consortiums[num_roaming_consortiums],
+ len / 2) < 0) {
+ wpa_printf(MSG_INFO,
+ "Invalid roaming_consortiums entry: %s",
+ pos);
+ return -1;
+ }
+ roaming_consortiums_len[num_roaming_consortiums] = len / 2;
+ num_roaming_consortiums++;
+
+ if (!end)
+ break;
+
+ if (num_roaming_consortiums >= MAX_ROAMING_CONS) {
+ wpa_printf(MSG_INFO,
+ "Too many roaming_consortiums OIs");
+ return -1;
+ }
+
+ pos = end + 1;
+ }
+
+ os_memcpy(cred->roaming_consortiums, roaming_consortiums,
+ sizeof(roaming_consortiums));
+ os_memcpy(cred->roaming_consortiums_len, roaming_consortiums_len,
+ sizeof(roaming_consortiums_len));
+ cred->num_roaming_consortiums = num_roaming_consortiums;
+
+ return 0;
+}
+
+
int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
const char *value, int line)
{
char *val;
size_t len;
+ int res;
if (os_strcmp(var, "temporary") == 0) {
cred->temporary = atoi(value);
@@ -3078,6 +3500,16 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
return 0;
}
+ if (os_strcmp(var, "roaming_consortiums") == 0) {
+ res = wpa_config_set_cred_roaming_consortiums(cred, val);
+ if (res < 0)
+ wpa_printf(MSG_ERROR,
+ "Line %d: invalid roaming_consortiums",
+ line);
+ os_free(val);
+ return res;
+ }
+
if (os_strcmp(var, "excluded_ssid") == 0) {
struct excluded_ssid *e;
@@ -3389,6 +3821,31 @@ char * wpa_config_get_cred_no_key(struct wpa_cred *cred, const char *var)
return buf;
}
+ if (os_strcmp(var, "roaming_consortiums") == 0) {
+ size_t buflen;
+ char *buf, *pos;
+ size_t i;
+
+ if (!cred->num_roaming_consortiums)
+ return NULL;
+ buflen = cred->num_roaming_consortiums *
+ MAX_ROAMING_CONS_OI_LEN * 2 + 1;
+ buf = os_malloc(buflen);
+ if (!buf)
+ return NULL;
+ pos = buf;
+ for (i = 0; i < cred->num_roaming_consortiums; i++) {
+ if (i > 0)
+ *pos++ = ',';
+ pos += wpa_snprintf_hex(
+ pos, buf + buflen - pos,
+ cred->roaming_consortiums[i],
+ cred->roaming_consortiums_len[i]);
+ }
+ *pos = '\0';
+ return buf;
+ }
+
if (os_strcmp(var, "excluded_ssid") == 0) {
unsigned int i;
char *buf, *end, *pos;
@@ -3646,6 +4103,7 @@ struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
config->bss_expiration_age = DEFAULT_BSS_EXPIRATION_AGE;
config->bss_expiration_scan_count = DEFAULT_BSS_EXPIRATION_SCAN_COUNT;
config->max_num_sta = DEFAULT_MAX_NUM_STA;
+ config->ap_isolate = DEFAULT_AP_ISOLATE;
config->access_network_type = DEFAULT_ACCESS_NETWORK_TYPE;
config->scan_cur_freq = DEFAULT_SCAN_CUR_FREQ;
config->wmm_ac_params[0] = ac_be;
@@ -3660,12 +4118,16 @@ struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
#ifdef CONFIG_MBO
config->mbo_cell_capa = DEFAULT_MBO_CELL_CAPA;
+ config->disassoc_imminent_rssi_threshold =
+ DEFAULT_DISASSOC_IMMINENT_RSSI_THRESHOLD;
+ config->oce = DEFAULT_OCE_SUPPORT;
#endif /* CONFIG_MBO */
if (ctrl_interface)
config->ctrl_interface = os_strdup(ctrl_interface);
if (driver_param)
config->driver_param = os_strdup(driver_param);
+ config->gas_rand_addr_lifetime = DEFAULT_RAND_ADDR_LIFETIME;
return config;
}
@@ -4072,6 +4534,21 @@ static int wpa_config_process_p2p_no_go_freq(
return 0;
}
+
+static int wpa_config_process_p2p_device_persistent_mac_addr(
+ const struct global_parse_data *data,
+ struct wpa_config *config, int line, const char *pos)
+{
+ if (hwaddr_aton2(pos, config->p2p_device_persistent_mac_addr) < 0) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: Invalid p2p_device_persistent_mac_addr '%s'",
+ line, pos);
+ return -1;
+ }
+
+ return 0;
+}
+
#endif /* CONFIG_P2P */
@@ -4271,6 +4748,7 @@ static const struct global_parse_data global_fields[] = {
{ FUNC_NO_VAR(load_dynamic_eap), 0 },
#ifdef CONFIG_WPS
{ FUNC(uuid), CFG_CHANGED_UUID },
+ { INT_RANGE(auto_uuid, 0, 1), 0 },
{ STR_RANGE(device_name, 0, WPS_DEV_NAME_MAX_LEN),
CFG_CHANGED_DEVICE_NAME },
{ STR_RANGE(manufacturer, 0, 64), CFG_CHANGED_WPS_STRING },
@@ -4281,6 +4759,7 @@ static const struct global_parse_data global_fields[] = {
{ FUNC(os_version), CFG_CHANGED_OS_VERSION },
{ STR(config_methods), CFG_CHANGED_CONFIG_METHODS },
{ INT_RANGE(wps_cred_processing, 0, 2), 0 },
+ { INT_RANGE(wps_cred_add_sae, 0, 1), 0 },
{ FUNC(wps_vendor_ext_m1), CFG_CHANGED_VENDOR_EXTENSION },
#endif /* CONFIG_WPS */
#ifdef CONFIG_P2P
@@ -4303,6 +4782,7 @@ static const struct global_parse_data global_fields[] = {
{ INT_RANGE(p2p_optimize_listen_chan, 0, 1), 0 },
{ INT(p2p_go_ht40), 0 },
{ INT(p2p_go_vht), 0 },
+ { INT(p2p_go_he), 0 },
{ INT(p2p_disabled), 0 },
{ INT_RANGE(p2p_go_ctwindow, 0, 127), 0 },
{ INT(p2p_no_group_iface), 0 },
@@ -4312,6 +4792,9 @@ static const struct global_parse_data global_fields[] = {
{ IPV4(ip_addr_start), 0 },
{ IPV4(ip_addr_end), 0 },
{ INT_RANGE(p2p_cli_probe, 0, 1), 0 },
+ { INT(p2p_device_random_mac_addr), 0 },
+ { FUNC(p2p_device_persistent_mac_addr), 0 },
+ { INT(p2p_interface_random_mac_addr), 0 },
#endif /* CONFIG_P2P */
{ FUNC(country), CFG_CHANGED_COUNTRY },
{ INT(bss_max_count), 0 },
@@ -4320,6 +4803,7 @@ static const struct global_parse_data global_fields[] = {
{ INT_RANGE(filter_ssids, 0, 1), 0 },
{ INT_RANGE(filter_rssi, -100, 0), 0 },
{ INT(max_num_sta), 0 },
+ { INT_RANGE(ap_isolate, 0, 1), 0 },
{ INT_RANGE(disassoc_low_ack, 0, 1), 0 },
#ifdef CONFIG_HS20
{ INT_RANGE(hs20, 0, 1), 0 },
@@ -4327,6 +4811,11 @@ static const struct global_parse_data global_fields[] = {
{ INT_RANGE(interworking, 0, 1), 0 },
{ FUNC(hessid), 0 },
{ INT_RANGE(access_network_type, 0, 15), 0 },
+ { INT_RANGE(go_interworking, 0, 1), 0 },
+ { INT_RANGE(go_access_network_type, 0, 15), 0 },
+ { INT_RANGE(go_internet, 0, 1), 0 },
+ { INT_RANGE(go_venue_group, 0, 255), 0 },
+ { INT_RANGE(go_venue_type, 0, 255), 0 },
{ INT_RANGE(pbc_in_m1, 0, 1), 0 },
{ STR(autoscan), 0 },
{ INT_RANGE(wps_nfc_dev_pw_id, 0x10, 0xffff),
@@ -4347,9 +4836,10 @@ static const struct global_parse_data global_fields[] = {
{ FUNC(freq_list), 0 },
{ INT(scan_cur_freq), 0 },
{ INT(sched_scan_interval), 0 },
+ { INT(sched_scan_start_delay), 0 },
{ INT(tdls_external_control), 0},
{ STR(osu_dir), 0 },
- { STR(wowlan_triggers), 0 },
+ { STR(wowlan_triggers), CFG_CHANGED_WOWLAN_TRIGGERS },
{ INT(p2p_search_delay), 0},
{ INT(mac_addr), 0 },
{ INT(rand_addr_lifetime), 0 },
@@ -4363,16 +4853,23 @@ static const struct global_parse_data global_fields[] = {
{ INT_RANGE(fst_priority, 1, FST_MAX_PRIO_VALUE), 0 },
{ INT_RANGE(fst_llt, 1, FST_MAX_LLT_MS), 0 },
#endif /* CONFIG_FST */
+ { INT_RANGE(cert_in_cb, 0, 1), 0 },
{ INT_RANGE(wpa_rsc_relaxation, 0, 1), 0 },
{ STR(sched_scan_plans), CFG_CHANGED_SCHED_SCAN_PLANS },
#ifdef CONFIG_MBO
{ STR(non_pref_chan), 0 },
{ INT_RANGE(mbo_cell_capa, MBO_CELL_CAPA_AVAILABLE,
MBO_CELL_CAPA_NOT_SUPPORTED), 0 },
-#endif /*CONFIG_MBO */
+ { INT_RANGE(disassoc_imminent_rssi_threshold, -120, 0), 0 },
+ { INT_RANGE(oce, 0, 3), 0 },
+#endif /* CONFIG_MBO */
{ INT(gas_address3), 0 },
{ INT_RANGE(ftm_responder, 0, 1), 0 },
{ INT_RANGE(ftm_initiator, 0, 1), 0 },
+ { INT(gas_rand_addr_lifetime), 0 },
+ { INT_RANGE(gas_rand_mac_addr, 0, 2), 0 },
+ { INT_RANGE(dpp_config_processing, 0, 2), 0 },
+ { INT_RANGE(coloc_intf_reporting, 0, 1), 0 },
};
#undef FUNC
diff --git a/freebsd/contrib/wpa/wpa_supplicant/config.h b/freebsd/contrib/wpa/wpa_supplicant/config.h
index 9d41fd17..a617ea18 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/config.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/config.h
@@ -32,6 +32,7 @@
#define DEFAULT_BSS_EXPIRATION_AGE 180
#define DEFAULT_BSS_EXPIRATION_SCAN_COUNT 2
#define DEFAULT_MAX_NUM_STA 128
+#define DEFAULT_AP_ISOLATE 0
#define DEFAULT_ACCESS_NETWORK_TYPE 15
#define DEFAULT_SCAN_CUR_FREQ 0
#define DEFAULT_P2P_SEARCH_DELAY 500
@@ -41,6 +42,8 @@
#define DEFAULT_P2P_GO_CTWINDOW 0
#define DEFAULT_WPA_RSC_RELAXATION 1
#define DEFAULT_MBO_CELL_CAPA MBO_CELL_CAPA_NOT_SUPPORTED
+#define DEFAULT_DISASSOC_IMMINENT_RSSI_THRESHOLD -75
+#define DEFAULT_OCE_SUPPORT OCE_STA
#include "config_ssid.h"
#include "wps/wps.h"
@@ -51,6 +54,9 @@
#include <machine/rtems-bsd-commands.h>
#endif /* __rtems__ */
+#define MAX_ROAMING_CONS 36
+#define MAX_ROAMING_CONS_OI_LEN 15
+
struct wpa_cred {
/**
* next - Next credential in the list
@@ -225,10 +231,43 @@ struct wpa_cred {
*/
size_t roaming_consortium_len;
+ /**
+ * required_roaming_consortium - Required Roaming Consortium OI
+ *
+ * If required_roaming_consortium_len is non-zero, this field contains
+ * the Roaming Consortium OI that is required to be advertised by the AP
+ * for the credential to be considered matching.
+ */
u8 required_roaming_consortium[15];
+
+ /**
+ * required_roaming_consortium_len - Length of required_roaming_consortium
+ */
size_t required_roaming_consortium_len;
/**
+ * roaming_consortiums - Roaming Consortium OI(s) memberships
+ *
+ * This field contains one or more OIs identifying the roaming
+ * consortiums of which the provider is a member. The list is sorted
+ * from the most preferred one to the least preferred one. A match
+ * between the Roaming Consortium OIs advertised by an AP and the OIs
+ * in this list indicates that successful authentication is possible.
+ * (Hotspot 2.0 PerProviderSubscription/<X+>/HomeSP/RoamingConsortiumOI)
+ */
+ u8 roaming_consortiums[MAX_ROAMING_CONS][MAX_ROAMING_CONS_OI_LEN];
+
+ /**
+ * roaming_consortiums_len - Length on roaming_consortiums[i]
+ */
+ size_t roaming_consortiums_len[MAX_ROAMING_CONS];
+
+ /**
+ * num_roaming_consortiums - Number of entries in roaming_consortiums
+ */
+ unsigned int num_roaming_consortiums;
+
+ /**
* eap_method - EAP method to use
*
* Pre-configured EAP method to use with this credential or %NULL to
@@ -337,6 +376,7 @@ struct wpa_cred {
#define CFG_CHANGED_NFC_PASSWORD_TOKEN BIT(15)
#define CFG_CHANGED_P2P_PASSPHRASE_LEN BIT(16)
#define CFG_CHANGED_SCHED_SCAN_PLANS BIT(17)
+#define CFG_CHANGED_WOWLAN_TRIGGERS BIT(18)
/**
* struct wpa_config - wpa_supplicant configuration data
@@ -628,6 +668,13 @@ struct wpa_config {
u8 uuid[16];
/**
+ * auto_uuid - Automatic UUID behavior
+ * 0 = generate static value based on the local MAC address (default)
+ * 1 = generate a random UUID every time wpa_supplicant starts
+ */
+ int auto_uuid;
+
+ /**
* device_name - Device Name (WPS)
* User-friendly description of device; up to 32 octets encoded in
* UTF-8
@@ -701,6 +748,16 @@ struct wpa_config {
*/
int wps_cred_processing;
+ /**
+ * wps_cred_add_sae - Whether to enable SAE automatically for WPS
+ *
+ * 0 = only add the explicitly listed WPA2-PSK configuration
+ * 1 = add both the WPA2-PSK and SAE configuration and enable PMF so
+ * that the station gets configured in WPA3-Personal transition mode
+ * (supports both WPA2-Personal (PSK) and WPA3-Personal (SAE) APs).
+ */
+ int wps_cred_add_sae;
+
#define MAX_SEC_DEVICE_TYPES 5
/**
* sec_device_types - Secondary Device Types (P2P)
@@ -836,6 +893,20 @@ struct wpa_config {
unsigned int max_num_sta;
/**
+ * ap_isolate - Whether to use client isolation feature
+ *
+ * Client isolation can be used to prevent low-level bridging of
+ * frames between associated stations in the BSS. By default,
+ * this bridging is allowed (ap_isolate=0); except in P2P GO case,
+ * where p2p_intra_bss parameter is used to determine whether to allow
+ * intra-BSS forwarding (ap_isolate = !p2p_intra_bss).
+ *
+ * 0 = do not enable AP isolation
+ * 1 = enable AP isolation
+ */
+ int ap_isolate;
+
+ /**
* freq_list - Array of allowed scan frequencies or %NULL for all
*
* This is an optional zero-terminated array of frequencies in
@@ -857,7 +928,7 @@ struct wpa_config {
unsigned int changed_parameters;
/**
- * disassoc_low_ack - Disassocicate stations with massive packet loss
+ * disassoc_low_ack - Disassociate stations with massive packet loss
*/
int disassoc_low_ack;
@@ -875,6 +946,34 @@ struct wpa_config {
*/
int access_network_type;
+ /**
+ * go_interworking - Whether Interworking for P2P GO is enabled
+ */
+ int go_interworking;
+
+ /**
+ * go_access_network_type - P2P GO Access Network Type
+ *
+ * This indicates which access network type to advertise if Interworking
+ * is enabled for P2P GO.
+ */
+ int go_access_network_type;
+
+ /**
+ * go_internet - Interworking: Internet connectivity (0 or 1)
+ */
+ int go_internet;
+
+ /**
+ * go_venue_group - Interworking: Venue group
+ */
+ int go_venue_group;
+
+ /**
+ * go_venue_type: Interworking: Venue type
+ */
+ int go_venue_type;
+
/**
* hessid - Homogenous ESS identifier
*
@@ -993,6 +1092,16 @@ struct wpa_config {
int p2p_go_vht;
/**
+ * p2p_go_he - Default mode for 11ax HE enable when operating as GO
+ *
+ * This will take effect for p2p_group_add, p2p_connect, and p2p_invite.
+ * Note that regulatory constraints and driver capabilities are
+ * consulted anyway, so setting it to 1 can't do real harm.
+ * By default: 0 (disabled)
+ */
+ int p2p_go_he;
+
+ /**
* p2p_go_ctwindow - CTWindow to use when operating as GO
*
* By default: 0 (no CTWindow). Values 0-127 can be used to indicate
@@ -1099,6 +1208,15 @@ struct wpa_config {
unsigned int sched_scan_interval;
/**
+ * sched_scan_start_delay - Schedule scan start delay before first scan
+ *
+ * Delay (in seconds) before scheduling first scan plan cycle. The
+ * driver may ignore this parameter and start immediately (or at any
+ * other time), if this feature is not supported.
+ */
+ unsigned int sched_scan_start_delay;
+
+ /**
* tdls_external_control - External control for TDLS setup requests
*
* Enable TDLS mode where external programs are given the control
@@ -1294,6 +1412,19 @@ struct wpa_config {
* mbo_cell_capa - Cellular capabilities for MBO
*/
enum mbo_cellular_capa mbo_cell_capa;
+
+ /**
+ * disassoc_imminent_rssi_threshold - RSSI threshold of candidate AP
+ * when disassociation imminent is set.
+ */
+ int disassoc_imminent_rssi_threshold;
+
+ /**
+ * oce - Enable OCE in STA and/or STA-CFON mode
+ * - Set BIT(0) to enable OCE in non-AP STA mode
+ * - Set BIT(1) to enable OCE in STA-CFON mode
+ */
+ unsigned int oce;
#endif /* CONFIG_MBO */
/**
@@ -1331,6 +1462,74 @@ struct wpa_config {
* wpa_supplicant.
*/
int ftm_initiator;
+
+ /**
+ * gas_rand_addr_lifetime - Lifetime of random MAC address for ANQP in
+ * seconds
+ */
+ unsigned int gas_rand_addr_lifetime;
+
+ /**
+ * gas_rand_mac_addr - GAS MAC address policy
+ *
+ * 0 = use permanent MAC address
+ * 1 = use random MAC address
+ * 2 = like 1, but maintain OUI (with local admin bit set)
+ */
+ int gas_rand_mac_addr;
+
+ /**
+ * dpp_config_processing - How to process DPP configuration
+ *
+ * 0 = report received configuration to an external program for
+ * processing; do not generate any network profile internally
+ * 1 = report received configuration to an external program and generate
+ * a network profile internally, but do not automatically connect
+ * to the created (disabled) profile; the network profile id is
+ * reported to external programs
+ * 2 = report received configuration to an external program, generate
+ * a network profile internally, try to connect to the created
+ * profile automatically
+ */
+ int dpp_config_processing;
+
+ /**
+ * coloc_intf_reporting - Colocated interference reporting
+ *
+ * dot11CoLocIntfReportingActivated
+ * 0 = disabled (false)
+ * 1 = enabled (true)
+ */
+ int coloc_intf_reporting;
+
+ /**
+ * p2p_device_random_mac_addr - P2P Device MAC address policy default
+ *
+ * 0 = use permanent MAC address
+ * 1 = use random MAC address on creating the interface if there is no
+ * persistent groups.
+ *
+ * By default, permanent MAC address is used.
+ */
+ int p2p_device_random_mac_addr;
+
+ /**
+ * p2p_device_persistent_mac_addr - Record last used MAC address
+ *
+ * If there are saved persistent groups, P2P cannot generate another
+ * random MAC address, and need to restore to last used MAC address.
+ */
+ u8 p2p_device_persistent_mac_addr[ETH_ALEN];
+
+ /**
+ * p2p_interface_random_mac_addr - P2P Interface MAC address policy default
+ *
+ * 0 = use permanent MAC address
+ * 1 = use random MAC address on creating the interface.
+ *
+ * By default, permanent MAC address is used.
+ */
+ int p2p_interface_random_mac_addr;
};
diff --git a/freebsd/contrib/wpa/wpa_supplicant/config_file.c b/freebsd/contrib/wpa/wpa_supplicant/config_file.c
index 09df6c14..e3e17e01 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/config_file.c
+++ b/freebsd/contrib/wpa/wpa_supplicant/config_file.c
@@ -21,6 +21,7 @@
#include "config.h"
#include "base64.h"
#include "uuid.h"
+#include "common/ieee802_1x_defs.h"
#include "p2p/p2p.h"
#include "eap_peer/eap_methods.h"
#include "eap_peer/eap.h"
@@ -138,9 +139,13 @@ static int wpa_config_validate_network(struct wpa_ssid *ssid, int line)
wpa_config_update_psk(ssid);
}
+ if (ssid->disabled == 2)
+ ssid->p2p_persistent_group = 1;
+
if ((ssid->group_cipher & WPA_CIPHER_CCMP) &&
- !(ssid->pairwise_cipher & WPA_CIPHER_CCMP) &&
- !(ssid->pairwise_cipher & WPA_CIPHER_NONE)) {
+ !(ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 |
+ WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256 |
+ WPA_CIPHER_NONE))) {
/* Group cipher cannot be stronger than the pairwise cipher. */
wpa_printf(MSG_DEBUG, "Line %d: removed CCMP from group cipher"
" list since it was not allowed for pairwise "
@@ -157,6 +162,15 @@ static int wpa_config_validate_network(struct wpa_ssid *ssid, int line)
errors++;
}
+#ifdef CONFIG_OCV
+ if (ssid->ocv && ssid->ieee80211w == NO_MGMT_FRAME_PROTECTION) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: PMF needs to be enabled whenever using OCV",
+ line);
+ errors++;
+ }
+#endif /* CONFIG_OCV */
+
return errors;
}
@@ -310,7 +324,7 @@ static struct wpa_config_blob * wpa_config_read_blob(FILE *f, int *line,
encoded_len += len;
}
- if (!end) {
+ if (!end || !encoded) {
wpa_printf(MSG_ERROR, "Line %d: blob was not terminated "
"properly", *line);
os_free(encoded);
@@ -395,7 +409,8 @@ struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp)
if (f == NULL) {
wpa_printf(MSG_ERROR, "Failed to open config file '%s', "
"error: %s", name, strerror(errno));
- os_free(config);
+ if (config != cfgp)
+ os_free(config);
return NULL;
}
@@ -461,7 +476,8 @@ struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp)
#ifndef WPA_IGNORE_CONFIG_ERRORS
if (errors) {
- wpa_config_free(config);
+ if (config != cfgp)
+ wpa_config_free(config);
config = NULL;
head = NULL;
}
@@ -479,7 +495,7 @@ static void write_str(FILE *f, const char *field, struct wpa_ssid *ssid)
if (value == NULL)
return;
fprintf(f, "\t%s=%s\n", field, value);
- os_free(value);
+ str_clear_free(value);
}
@@ -501,6 +517,17 @@ static void write_bssid(FILE *f, struct wpa_ssid *ssid)
}
+static void write_bssid_hint(FILE *f, struct wpa_ssid *ssid)
+{
+ char *value = wpa_config_get(ssid, "bssid_hint");
+
+ if (!value)
+ return;
+ fprintf(f, "\tbssid_hint=%s\n", value);
+ os_free(value);
+}
+
+
static void write_psk(FILE *f, struct wpa_ssid *ssid)
{
char *value;
@@ -580,6 +607,22 @@ static void write_group(FILE *f, struct wpa_ssid *ssid)
}
+static void write_group_mgmt(FILE *f, struct wpa_ssid *ssid)
+{
+ char *value;
+
+ if (!ssid->group_mgmt_cipher)
+ return;
+
+ value = wpa_config_get(ssid, "group_mgmt");
+ if (!value)
+ return;
+ if (value[0])
+ fprintf(f, "\tgroup_mgmt=%s\n", value);
+ os_free(value);
+}
+
+
static void write_auth_alg(FILE *f, struct wpa_ssid *ssid)
{
char *value;
@@ -664,6 +707,40 @@ static void write_psk_list(FILE *f, struct wpa_ssid *ssid)
#endif /* CONFIG_P2P */
+#ifdef CONFIG_MACSEC
+
+static void write_mka_cak(FILE *f, struct wpa_ssid *ssid)
+{
+ char *value;
+
+ if (!(ssid->mka_psk_set & MKA_PSK_SET_CAK))
+ return;
+
+ value = wpa_config_get(ssid, "mka_cak");
+ if (!value)
+ return;
+ fprintf(f, "\tmka_cak=%s\n", value);
+ os_free(value);
+}
+
+
+static void write_mka_ckn(FILE *f, struct wpa_ssid *ssid)
+{
+ char *value;
+
+ if (!(ssid->mka_psk_set & MKA_PSK_SET_CKN))
+ return;
+
+ value = wpa_config_get(ssid, "mka_ckn");
+ if (!value)
+ return;
+ fprintf(f, "\tmka_ckn=%s\n", value);
+ os_free(value);
+}
+
+#endif /* CONFIG_MACSEC */
+
+
static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
{
int i;
@@ -677,15 +754,19 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
STR(ssid);
INT(scan_ssid);
write_bssid(f, ssid);
+ write_bssid_hint(f, ssid);
write_str(f, "bssid_blacklist", ssid);
write_str(f, "bssid_whitelist", ssid);
write_psk(f, ssid);
INT(mem_only_psk);
+ STR(sae_password);
+ STR(sae_password_id);
write_proto(f, ssid);
write_key_mgmt(f, ssid);
INT_DEF(bg_scan_period, DEFAULT_BG_SCAN_PERIOD);
write_pairwise(f, ssid);
write_group(f, ssid);
+ write_group_mgmt(f, ssid);
write_auth_alg(f, ssid);
STR(bgscan);
STR(autoscan);
@@ -694,6 +775,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
write_eap(f, ssid);
STR(identity);
STR(anonymous_identity);
+ STR(imsi_identity);
STR(password);
STR(ca_cert);
STR(ca_path);
@@ -702,6 +784,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
STR(private_key_passwd);
STR(dh_file);
STR(subject_match);
+ STR(check_cert_subject);
STR(altsubject_match);
STR(domain_suffix_match);
STR(domain_match);
@@ -712,6 +795,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
STR(private_key2_passwd);
STR(dh_file2);
STR(subject_match2);
+ STR(check_cert_subject2);
STR(altsubject_match2);
STR(domain_suffix_match2);
STR(domain_match2);
@@ -754,11 +838,16 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
#endif /* CONFIG_ACS */
write_int(f, "proactive_key_caching", ssid->proactive_key_caching, -1);
INT(disabled);
- INT(peerkey);
INT(mixed_cell);
- INT(max_oper_chwidth);
+ INT(vht);
+ INT_DEF(ht, 1);
+ INT(ht40);
+ INT_DEF(max_oper_chwidth, DEFAULT_MAX_OPER_CHWIDTH);
+ INT(vht_center_freq1);
+ INT(vht_center_freq2);
INT(pbss);
INT(wps_disabled);
+ INT(fils_dh_group);
#ifdef CONFIG_IEEE80211W
write_int(f, "ieee80211w", ssid->ieee80211w,
MGMT_FRAME_PROTECTION_DEFAULT);
@@ -774,9 +863,17 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
INT(beacon_int);
#ifdef CONFIG_MACSEC
INT(macsec_policy);
+ write_mka_cak(f, ssid);
+ write_mka_ckn(f, ssid);
+ INT(macsec_integ_only);
+ INT(macsec_replay_protect);
+ INT(macsec_replay_window);
+ INT(macsec_port);
+ INT_DEF(mka_priority, DEFAULT_PRIO_NOT_KEY_SERVER);
#endif /* CONFIG_MACSEC */
#ifdef CONFIG_HS20
INT(update_identifier);
+ STR(roaming_consortium_selection);
#endif /* CONFIG_HS20 */
write_int(f, "mac_addr", ssid->mac_addr, -1);
#ifdef CONFIG_MESH
@@ -785,16 +882,28 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
INT_DEF(dot11MeshRetryTimeout, DEFAULT_MESH_RETRY_TIMEOUT);
INT_DEF(dot11MeshConfirmTimeout, DEFAULT_MESH_CONFIRM_TIMEOUT);
INT_DEF(dot11MeshHoldingTimeout, DEFAULT_MESH_HOLDING_TIMEOUT);
+ INT_DEF(mesh_rssi_threshold, DEFAULT_MESH_RSSI_THRESHOLD);
#endif /* CONFIG_MESH */
INT(wpa_ptk_rekey);
INT(group_rekey);
INT(ignore_broadcast_ssid);
+#ifdef CONFIG_DPP
+ STR(dpp_connector);
+ STR(dpp_netaccesskey);
+ INT(dpp_netaccesskey_expiry);
+ STR(dpp_csign);
+#endif /* CONFIG_DPP */
+ INT(owe_group);
+ INT(owe_only);
+ INT(multi_ap_backhaul_sta);
#ifdef CONFIG_HT_OVERRIDES
INT_DEF(disable_ht, DEFAULT_DISABLE_HT);
INT_DEF(disable_ht40, DEFAULT_DISABLE_HT40);
INT_DEF(disable_sgi, DEFAULT_DISABLE_SGI);
INT_DEF(disable_ldpc, DEFAULT_DISABLE_LDPC);
INT(ht40_intolerant);
+ INT_DEF(tx_stbc, DEFAULT_TX_STBC);
+ INT_DEF(rx_stbc, DEFAULT_RX_STBC);
INT_DEF(disable_max_amsdu, DEFAULT_DISABLE_MAX_AMSDU);
INT_DEF(ampdu_factor, DEFAULT_AMPDU_FACTOR);
INT_DEF(ampdu_density, DEFAULT_AMPDU_DENSITY);
@@ -951,6 +1060,20 @@ static void wpa_config_write_cred(FILE *f, struct wpa_cred *cred)
fprintf(f, "\n");
}
+ if (cred->num_roaming_consortiums) {
+ size_t j;
+
+ fprintf(f, "\troaming_consortiums=\"");
+ for (i = 0; i < cred->num_roaming_consortiums; i++) {
+ if (i > 0)
+ fprintf(f, ",");
+ for (j = 0; j < cred->roaming_consortiums_len[i]; j++)
+ fprintf(f, "%02x",
+ cred->roaming_consortiums[i][j]);
+ }
+ fprintf(f, "\"\n");
+ }
+
if (cred->sim_num != DEFAULT_USER_SELECTED_SIM)
fprintf(f, "\tsim_num=%d\n", cred->sim_num);
}
@@ -1041,6 +1164,8 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
uuid_bin2str(config->uuid, buf, sizeof(buf));
fprintf(f, "uuid=%s\n", buf);
}
+ if (config->auto_uuid)
+ fprintf(f, "auto_uuid=%d\n", config->auto_uuid);
if (config->device_name)
fprintf(f, "device_name=%s\n", config->device_name);
if (config->manufacturer)
@@ -1066,6 +1191,9 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
if (config->wps_cred_processing)
fprintf(f, "wps_cred_processing=%d\n",
config->wps_cred_processing);
+ if (config->wps_cred_add_sae)
+ fprintf(f, "wps_cred_add_sae=%d\n",
+ config->wps_cred_add_sae);
if (config->wps_vendor_ext_m1) {
int i, len = wpabuf_len(config->wps_vendor_ext_m1);
const u8 *p = wpabuf_head_u8(config->wps_vendor_ext_m1);
@@ -1078,6 +1206,17 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
}
#endif /* CONFIG_WPS */
#ifdef CONFIG_P2P
+ {
+ int i;
+ char _buf[WPS_DEV_TYPE_BUFSIZE], *buf;
+
+ for (i = 0; i < config->num_sec_device_types; i++) {
+ buf = wps_dev_type_bin2str(config->sec_device_type[i],
+ _buf, sizeof(_buf));
+ if (buf)
+ fprintf(f, "sec_device_type=%s\n", buf);
+ }
+ }
if (config->p2p_listen_reg_class)
fprintf(f, "p2p_listen_reg_class=%d\n",
config->p2p_listen_reg_class);
@@ -1130,6 +1269,8 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
fprintf(f, "p2p_go_ht40=%d\n", config->p2p_go_ht40);
if (config->p2p_go_vht)
fprintf(f, "p2p_go_vht=%d\n", config->p2p_go_vht);
+ if (config->p2p_go_he)
+ fprintf(f, "p2p_go_he=%d\n", config->p2p_go_he);
if (config->p2p_go_ctwindow != DEFAULT_P2P_GO_CTWINDOW)
fprintf(f, "p2p_go_ctwindow=%d\n", config->p2p_go_ctwindow);
if (config->p2p_disabled)
@@ -1177,8 +1318,12 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
config->bss_expiration_scan_count);
if (config->filter_ssids)
fprintf(f, "filter_ssids=%d\n", config->filter_ssids);
+ if (config->filter_rssi)
+ fprintf(f, "filter_rssi=%d\n", config->filter_rssi);
if (config->max_num_sta != DEFAULT_MAX_NUM_STA)
fprintf(f, "max_num_sta=%u\n", config->max_num_sta);
+ if (config->ap_isolate != DEFAULT_AP_ISOLATE)
+ fprintf(f, "ap_isolate=%u\n", config->ap_isolate);
if (config->disassoc_low_ack)
fprintf(f, "disassoc_low_ack=%d\n", config->disassoc_low_ack);
#ifdef CONFIG_HS20
@@ -1193,6 +1338,17 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
if (config->access_network_type != DEFAULT_ACCESS_NETWORK_TYPE)
fprintf(f, "access_network_type=%d\n",
config->access_network_type);
+ if (config->go_interworking)
+ fprintf(f, "go_interworking=%d\n", config->go_interworking);
+ if (config->go_access_network_type)
+ fprintf(f, "go_access_network_type=%d\n",
+ config->go_access_network_type);
+ if (config->go_internet)
+ fprintf(f, "go_internet=%d\n", config->go_internet);
+ if (config->go_venue_group)
+ fprintf(f, "go_venue_group=%d\n", config->go_venue_group);
+ if (config->go_venue_type)
+ fprintf(f, "go_venue_type=%d\n", config->go_venue_type);
#endif /* CONFIG_INTERWORKING */
if (config->pbc_in_m1)
fprintf(f, "pbc_in_m1=%d\n", config->pbc_in_m1);
@@ -1228,7 +1384,7 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
if (config->sae_groups) {
int i;
fprintf(f, "sae_groups=");
- for (i = 0; config->sae_groups[i] >= 0; i++) {
+ for (i = 0; config->sae_groups[i] > 0; i++) {
fprintf(f, "%s%d", i > 0 ? " " : "",
config->sae_groups[i]);
}
@@ -1266,6 +1422,10 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
fprintf(f, "sched_scan_interval=%u\n",
config->sched_scan_interval);
+ if (config->sched_scan_start_delay)
+ fprintf(f, "sched_scan_start_delay=%u\n",
+ config->sched_scan_start_delay);
+
if (config->external_sim)
fprintf(f, "external_sim=%d\n", config->external_sim);
@@ -1280,6 +1440,9 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
if (config->bgscan)
fprintf(f, "bgscan=\"%s\"\n", config->bgscan);
+ if (config->autoscan)
+ fprintf(f, "autoscan=%s\n", config->autoscan);
+
if (config->p2p_search_delay != DEFAULT_P2P_SEARCH_DELAY)
fprintf(f, "p2p_search_delay=%u\n",
config->p2p_search_delay);
@@ -1337,6 +1500,12 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
fprintf(f, "non_pref_chan=%s\n", config->non_pref_chan);
if (config->mbo_cell_capa != DEFAULT_MBO_CELL_CAPA)
fprintf(f, "mbo_cell_capa=%u\n", config->mbo_cell_capa);
+ if (config->disassoc_imminent_rssi_threshold !=
+ DEFAULT_DISASSOC_IMMINENT_RSSI_THRESHOLD)
+ fprintf(f, "disassoc_imminent_rssi_threshold=%d\n",
+ config->disassoc_imminent_rssi_threshold);
+ if (config->oce != DEFAULT_OCE_SUPPORT)
+ fprintf(f, "oce=%u\n", config->oce);
#endif /* CONFIG_MBO */
if (config->gas_address3)
@@ -1346,6 +1515,37 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
fprintf(f, "ftm_responder=%d\n", config->ftm_responder);
if (config->ftm_initiator)
fprintf(f, "ftm_initiator=%d\n", config->ftm_initiator);
+
+ if (config->osu_dir)
+ fprintf(f, "osu_dir=%s\n", config->osu_dir);
+
+ if (config->fst_group_id)
+ fprintf(f, "fst_group_id=%s\n", config->fst_group_id);
+ if (config->fst_priority)
+ fprintf(f, "fst_priority=%d\n", config->fst_priority);
+ if (config->fst_llt)
+ fprintf(f, "fst_llt=%d\n", config->fst_llt);
+
+ if (config->gas_rand_addr_lifetime != DEFAULT_RAND_ADDR_LIFETIME)
+ fprintf(f, "gas_rand_addr_lifetime=%u\n",
+ config->gas_rand_addr_lifetime);
+ if (config->gas_rand_mac_addr)
+ fprintf(f, "gas_rand_mac_addr=%d\n", config->gas_rand_mac_addr);
+ if (config->dpp_config_processing)
+ fprintf(f, "dpp_config_processing=%d\n",
+ config->dpp_config_processing);
+ if (config->coloc_intf_reporting)
+ fprintf(f, "coloc_intf_reporting=%d\n",
+ config->coloc_intf_reporting);
+ if (config->p2p_device_random_mac_addr)
+ fprintf(f, "p2p_device_random_mac_addr=%d\n",
+ config->p2p_device_random_mac_addr);
+ if (!is_zero_ether_addr(config->p2p_device_persistent_mac_addr))
+ fprintf(f, "p2p_device_persistent_mac_addr=" MACSTR "\n",
+ MAC2STR(config->p2p_device_persistent_mac_addr));
+ if (config->p2p_interface_random_mac_addr)
+ fprintf(f, "p2p_interface_random_mac_addr=%d\n",
+ config->p2p_interface_random_mac_addr);
}
#endif /* CONFIG_NO_CONFIG_WRITE */
diff --git a/freebsd/contrib/wpa/wpa_supplicant/config_ssid.h b/freebsd/contrib/wpa/wpa_supplicant/config_ssid.h
index 010b594a..1b2b1f1a 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/config_ssid.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/config_ssid.h
@@ -28,14 +28,18 @@
#define DEFAULT_MESH_RETRY_TIMEOUT 40
#define DEFAULT_MESH_CONFIRM_TIMEOUT 40
#define DEFAULT_MESH_HOLDING_TIMEOUT 40
+#define DEFAULT_MESH_RSSI_THRESHOLD 1 /* no change */
#define DEFAULT_DISABLE_HT 0
#define DEFAULT_DISABLE_HT40 0
#define DEFAULT_DISABLE_SGI 0
#define DEFAULT_DISABLE_LDPC 0
+#define DEFAULT_TX_STBC -1 /* no change */
+#define DEFAULT_RX_STBC -1 /* no change */
#define DEFAULT_DISABLE_MAX_AMSDU -1 /* no change */
#define DEFAULT_AMPDU_FACTOR -1 /* no change */
#define DEFAULT_AMPDU_DENSITY -1 /* no change */
#define DEFAULT_USER_SELECTED_SIM 1
+#define DEFAULT_MAX_OPER_CHWIDTH -1
struct psk_list_entry {
struct dl_list list;
@@ -146,6 +150,19 @@ struct wpa_ssid {
int bssid_set;
/**
+ * bssid_hint - BSSID hint
+ *
+ * If set, this is configured to the driver as a preferred initial BSSID
+ * while connecting to this network.
+ */
+ u8 bssid_hint[ETH_ALEN];
+
+ /**
+ * bssid_hint_set - Whether BSSID hint is configured for this network
+ */
+ int bssid_hint_set;
+
+ /**
* go_p2p_dev_addr - GO's P2P Device Address or all zeros if not set
*/
u8 go_p2p_dev_addr[ETH_ALEN];
@@ -170,6 +187,24 @@ struct wpa_ssid {
char *passphrase;
/**
+ * sae_password - SAE password
+ *
+ * This parameter can be used to set a password for SAE. By default, the
+ * passphrase value is used if this separate parameter is not used, but
+ * passphrase follows the WPA-PSK constraints (8..63 characters) even
+ * though SAE passwords do not have such constraints.
+ */
+ char *sae_password;
+
+ /**
+ * sae_password_id - SAE password identifier
+ *
+ * This parameter can be used to identify a specific SAE password. If
+ * not included, the default SAE password is used instead.
+ */
+ char *sae_password_id;
+
+ /**
* ext_psk - PSK/passphrase name in external storage
*
* If this is set, PSK/passphrase will be fetched from external storage
@@ -196,6 +231,15 @@ struct wpa_ssid {
int group_cipher;
/**
+ * group_mgmt_cipher - Bitfield of allowed group management ciphers
+ *
+ * This is a bitfield of WPA_CIPHER_AES_128_CMAC and WPA_CIPHER_BIP_*
+ * values. If 0, no constraint is used for the cipher, i.e., whatever
+ * the AP uses is accepted.
+ */
+ int group_mgmt_cipher;
+
+ /**
* key_mgmt - Bitfield of allowed key management protocols
*
* WPA_KEY_MGMT_*
@@ -392,17 +436,6 @@ struct wpa_ssid {
int disabled_for_connect;
/**
- * peerkey - Whether PeerKey handshake for direct links is allowed
- *
- * This is only used when both RSN/WPA2 and IEEE 802.11e (QoS) are
- * enabled.
- *
- * 0 = disabled (default)
- * 1 = enabled
- */
- int peerkey;
-
- /**
* id_str - Network identifier string for external scripts
*
* This value is passed to external ctrl_iface monitors in
@@ -427,6 +460,17 @@ struct wpa_ssid {
enum mfp_options ieee80211w;
#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_OCV
+ /**
+ * ocv - Enable/disable operating channel validation
+ *
+ * If this parameter is set to 1, stations will exchange OCI element
+ * to cryptographically verify the operating channel. Setting this
+ * parameter to 0 disables this option. Default value: 0.
+ */
+ int ocv;
+#endif /* CONFIG_OCV */
+
/**
* frequency - Channel frequency in megahertz (MHz) for IBSS
*
@@ -470,12 +514,16 @@ struct wpa_ssid {
int dot11MeshConfirmTimeout; /* msec */
int dot11MeshHoldingTimeout; /* msec */
+ int ht;
int ht40;
int vht;
- u8 max_oper_chwidth;
+ int he;
+ int max_oper_chwidth;
+
+ unsigned int vht_center_freq1;
unsigned int vht_center_freq2;
/**
@@ -650,6 +698,22 @@ struct wpa_ssid {
* By default (empty string): Use whatever the OS has configured.
*/
char *ht_mcs;
+
+ /**
+ * tx_stbc - Indicate STBC support for TX streams
+ *
+ * Value: -1..1, by default (-1): use whatever the OS or card has
+ * configured. See IEEE Std 802.11-2016, 9.4.2.56.2.
+ */
+ int tx_stbc;
+
+ /**
+ * rx_stbc - Indicate STBC support for RX streams
+ *
+ * Value: -1..3, by default (-1): use whatever the OS or card has
+ * configured. See IEEE Std 802.11-2016, 9.4.2.56.2.
+ */
+ int rx_stbc;
#endif /* CONFIG_HT_OVERRIDES */
#ifdef CONFIG_VHT_OVERRIDES
@@ -728,10 +792,100 @@ struct wpa_ssid {
* determine whether to use a secure session or not.
*/
int macsec_policy;
+
+ /**
+ * macsec_integ_only - Determines how MACsec are transmitted
+ *
+ * This setting applies only when MACsec is in use, i.e.,
+ * - macsec_policy is enabled
+ * - the key server has decided to enable MACsec
+ *
+ * 0: Encrypt traffic (default)
+ * 1: Integrity only
+ */
+ int macsec_integ_only;
+
+ /**
+ * macsec_replay_protect - Enable MACsec replay protection
+ *
+ * This setting applies only when MACsec is in use, i.e.,
+ * - macsec_policy is enabled
+ * - the key server has decided to enable MACsec
+ *
+ * 0: Replay protection disabled (default)
+ * 1: Replay protection enabled
+ */
+ int macsec_replay_protect;
+
+ /**
+ * macsec_replay_window - MACsec replay protection window
+ *
+ * A window in which replay is tolerated, to allow receipt of frames
+ * that have been misordered by the network.
+ *
+ * This setting applies only when MACsec replay protection active, i.e.,
+ * - macsec_replay_protect is enabled
+ * - the key server has decided to enable MACsec
+ *
+ * 0: No replay window, strict check (default)
+ * 1..2^32-1: number of packets that could be misordered
+ */
+ u32 macsec_replay_window;
+
+ /**
+ * macsec_port - MACsec port (in SCI)
+ *
+ * Port component of the SCI.
+ *
+ * Range: 1-65534 (default: 1)
+ */
+ int macsec_port;
+
+ /**
+ * mka_priority - Priority of MKA Actor
+ *
+ * Range: 0-255 (default: 255)
+ */
+ int mka_priority;
+
+ /**
+ * mka_ckn - MKA pre-shared CKN
+ */
+#define MACSEC_CKN_MAX_LEN 32
+ size_t mka_ckn_len;
+ u8 mka_ckn[MACSEC_CKN_MAX_LEN];
+
+ /**
+ * mka_cak - MKA pre-shared CAK
+ */
+#define MACSEC_CAK_MAX_LEN 32
+ size_t mka_cak_len;
+ u8 mka_cak[MACSEC_CAK_MAX_LEN];
+
+#define MKA_PSK_SET_CKN BIT(0)
+#define MKA_PSK_SET_CAK BIT(1)
+#define MKA_PSK_SET (MKA_PSK_SET_CKN | MKA_PSK_SET_CAK)
+ /**
+ * mka_psk_set - Whether mka_ckn and mka_cak are set
+ */
+ u8 mka_psk_set;
#endif /* CONFIG_MACSEC */
#ifdef CONFIG_HS20
int update_identifier;
+
+ /**
+ * roaming_consortium_selection - Roaming Consortium Selection
+ *
+ * The matching Roaming Consortium OI that was used to generate this
+ * network profile.
+ */
+ u8 *roaming_consortium_selection;
+
+ /**
+ * roaming_consortium_selection_len - roaming_consortium_selection len
+ */
+ size_t roaming_consortium_selection_len;
#endif /* CONFIG_HS20 */
unsigned int wps_run;
@@ -758,12 +912,99 @@ struct wpa_ssid {
int no_auto_peer;
/**
+ * mesh_rssi_threshold - Set mesh parameter mesh_rssi_threshold (dBm)
+ *
+ * -255..-1 = threshold value in dBm
+ * 0 = not using RSSI threshold
+ * 1 = do not change driver default
+ */
+ int mesh_rssi_threshold;
+
+ /**
* wps_disabled - WPS disabled in AP mode
*
* 0 = WPS enabled and configured (default)
* 1 = WPS disabled
*/
int wps_disabled;
+
+ /**
+ * fils_dh_group - FILS DH Group
+ *
+ * 0 = PFS disabled with FILS shared key authentication
+ * 1-65535 DH Group to use for FILS PFS
+ */
+ int fils_dh_group;
+
+ /**
+ * dpp_connector - DPP Connector (signedConnector as string)
+ */
+ char *dpp_connector;
+
+ /**
+ * dpp_netaccesskey - DPP netAccessKey (own private key)
+ */
+ u8 *dpp_netaccesskey;
+
+ /**
+ * dpp_netaccesskey_len - DPP netAccessKey length in octets
+ */
+ size_t dpp_netaccesskey_len;
+
+ /**
+ * net_access_key_expiry - DPP netAccessKey expiry in UNIX time stamp
+ *
+ * 0 indicates no expiration.
+ */
+ unsigned int dpp_netaccesskey_expiry;
+
+ /**
+ * dpp_csign - C-sign-key (Configurator public key)
+ */
+ u8 *dpp_csign;
+
+ /**
+ * dpp_csign_len - C-sign-key length in octets
+ */
+ size_t dpp_csign_len;
+
+ /**
+ * owe_group - OWE DH Group
+ *
+ * 0 = use default (19) first and then try all supported groups one by
+ * one if AP rejects the selected group
+ * 1-65535 DH Group to use for OWE
+ *
+ * Groups 19 (NIST P-256), 20 (NIST P-384), and 21 (NIST P-521) are
+ * currently supported.
+ */
+ int owe_group;
+
+ /**
+ * owe_only - OWE-only mode (disable transition mode)
+ *
+ * 0 = enable transition mode (allow connection to either OWE or open
+ * BSS)
+ * 1 = disable transition mode (allow connection only with OWE)
+ */
+ int owe_only;
+
+ /**
+ * owe_transition_bss_select_count - OWE transition BSS select count
+ *
+ * This is an internally used variable (i.e., not used in external
+ * configuration) to track the number of selection attempts done for
+ * OWE BSS in transition mode. This allows fallback to an open BSS if
+ * the selection attempts for OWE BSS exceed the configured threshold.
+ */
+ int owe_transition_bss_select_count;
+
+ /**
+ * multi_ap_backhaul_sta - Multi-AP backhaul STA
+ * 0 = normal (non-Multi-AP) station
+ * 1 = Multi-AP backhaul station
+ */
+ int multi_ap_backhaul_sta;
};
#endif /* CONFIG_SSID_H */
diff --git a/freebsd/contrib/wpa/wpa_supplicant/ctrl_iface.c b/freebsd/contrib/wpa/wpa_supplicant/ctrl_iface.c
index 9699c784..c7bcfef1 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/ctrl_iface.c
+++ b/freebsd/contrib/wpa/wpa_supplicant/ctrl_iface.c
@@ -2,7 +2,7 @@
/*
* WPA Supplicant / Control interface (shared code for all backends)
- * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -22,6 +22,9 @@
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
#include "common/wpa_ctrl.h"
+#ifdef CONFIG_DPP
+#include "common/dpp.h"
+#endif /* CONFIG_DPP */
#include "crypto/tls.h"
#include "ap/hostapd.h"
#include "eap_peer/eap.h"
@@ -54,6 +57,8 @@
#include "offchannel.h"
#include "drivers/driver.h"
#include "mesh.h"
+#include "dpp_supplicant.h"
+#include "sme.h"
static int wpa_supplicant_global_iface_list(struct wpa_global *global,
char *buf, int len);
@@ -63,6 +68,7 @@ static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s,
char *val);
+
static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val)
{
char *pos;
@@ -341,6 +347,75 @@ static int wpas_ctrl_iface_set_lci(struct wpa_supplicant *wpa_s,
}
+static int
+wpas_ctrl_set_relative_rssi(struct wpa_supplicant *wpa_s, const char *cmd)
+{
+ int relative_rssi;
+
+ if (os_strcmp(cmd, "disable") == 0) {
+ wpa_s->srp.relative_rssi_set = 0;
+ return 0;
+ }
+
+ relative_rssi = atoi(cmd);
+ if (relative_rssi < 0 || relative_rssi > 100)
+ return -1;
+ wpa_s->srp.relative_rssi = relative_rssi;
+ wpa_s->srp.relative_rssi_set = 1;
+ return 0;
+}
+
+
+static int wpas_ctrl_set_relative_band_adjust(struct wpa_supplicant *wpa_s,
+ const char *cmd)
+{
+ char *pos;
+ int adjust_rssi;
+
+ /* <band>:adjust_value */
+ pos = os_strchr(cmd, ':');
+ if (!pos)
+ return -1;
+ pos++;
+ adjust_rssi = atoi(pos);
+ if (adjust_rssi < -100 || adjust_rssi > 100)
+ return -1;
+
+ if (os_strncmp(cmd, "2G", 2) == 0)
+ wpa_s->srp.relative_adjust_band = WPA_SETBAND_2G;
+ else if (os_strncmp(cmd, "5G", 2) == 0)
+ wpa_s->srp.relative_adjust_band = WPA_SETBAND_5G;
+ else
+ return -1;
+
+ wpa_s->srp.relative_adjust_rssi = adjust_rssi;
+
+ return 0;
+}
+
+
+static int wpas_ctrl_iface_set_ric_ies(struct wpa_supplicant *wpa_s,
+ const char *cmd)
+{
+ struct wpabuf *ric_ies;
+
+ if (*cmd == '\0' || os_strcmp(cmd, "\"\"") == 0) {
+ wpabuf_free(wpa_s->ric_ies);
+ wpa_s->ric_ies = NULL;
+ return 0;
+ }
+
+ ric_ies = wpabuf_parse_bin(cmd);
+ if (!ric_ies)
+ return -1;
+
+ wpabuf_free(wpa_s->ric_ies);
+ wpa_s->ric_ies = ric_ies;
+
+ return 0;
+}
+
+
static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
char *cmd)
{
@@ -367,16 +442,29 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
-1, -1, -1, atoi(value));
} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
- atoi(value)))
+ atoi(value))) {
ret = -1;
+ } else {
+ value[-1] = '=';
+ wpa_config_process_global(wpa_s->conf, cmd, -1);
+ }
} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
0) {
if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
- atoi(value)))
+ atoi(value))) {
ret = -1;
+ } else {
+ value[-1] = '=';
+ wpa_config_process_global(wpa_s->conf, cmd, -1);
+ }
} else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
- if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value)))
+ if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
+ atoi(value))) {
ret = -1;
+ } else {
+ value[-1] = '=';
+ wpa_config_process_global(wpa_s->conf, cmd, -1);
+ }
} else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) {
wpa_s->wps_fragment_size = atoi(value);
#ifdef CONFIG_WPS_TESTING
@@ -496,6 +584,59 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
ret = set_disallow_aps(wpa_s, value);
} else if (os_strcasecmp(cmd, "no_keep_alive") == 0) {
wpa_s->no_keep_alive = !!atoi(value);
+#ifdef CONFIG_DPP
+ } else if (os_strcasecmp(cmd, "dpp_configurator_params") == 0) {
+ os_free(wpa_s->dpp_configurator_params);
+ wpa_s->dpp_configurator_params = os_strdup(value);
+ } else if (os_strcasecmp(cmd, "dpp_init_max_tries") == 0) {
+ wpa_s->dpp_init_max_tries = atoi(value);
+ } else if (os_strcasecmp(cmd, "dpp_init_retry_time") == 0) {
+ wpa_s->dpp_init_retry_time = atoi(value);
+ } else if (os_strcasecmp(cmd, "dpp_resp_wait_time") == 0) {
+ wpa_s->dpp_resp_wait_time = atoi(value);
+ } else if (os_strcasecmp(cmd, "dpp_resp_max_tries") == 0) {
+ wpa_s->dpp_resp_max_tries = atoi(value);
+ } else if (os_strcasecmp(cmd, "dpp_resp_retry_time") == 0) {
+ wpa_s->dpp_resp_retry_time = atoi(value);
+#ifdef CONFIG_TESTING_OPTIONS
+ } else if (os_strcasecmp(cmd, "dpp_pkex_own_mac_override") == 0) {
+ if (hwaddr_aton(value, dpp_pkex_own_mac_override))
+ ret = -1;
+ } else if (os_strcasecmp(cmd, "dpp_pkex_peer_mac_override") == 0) {
+ if (hwaddr_aton(value, dpp_pkex_peer_mac_override))
+ ret = -1;
+ } else if (os_strcasecmp(cmd, "dpp_pkex_ephemeral_key_override") == 0) {
+ size_t hex_len = os_strlen(value);
+
+ if (hex_len >
+ 2 * sizeof(dpp_pkex_ephemeral_key_override))
+ ret = -1;
+ else if (hexstr2bin(value, dpp_pkex_ephemeral_key_override,
+ hex_len / 2))
+ ret = -1;
+ else
+ dpp_pkex_ephemeral_key_override_len = hex_len / 2;
+ } else if (os_strcasecmp(cmd, "dpp_protocol_key_override") == 0) {
+ size_t hex_len = os_strlen(value);
+
+ if (hex_len > 2 * sizeof(dpp_protocol_key_override))
+ ret = -1;
+ else if (hexstr2bin(value, dpp_protocol_key_override,
+ hex_len / 2))
+ ret = -1;
+ else
+ dpp_protocol_key_override_len = hex_len / 2;
+ } else if (os_strcasecmp(cmd, "dpp_nonce_override") == 0) {
+ size_t hex_len = os_strlen(value);
+
+ if (hex_len > 2 * sizeof(dpp_nonce_override))
+ ret = -1;
+ else if (hexstr2bin(value, dpp_nonce_override, hex_len / 2))
+ ret = -1;
+ else
+ dpp_nonce_override_len = hex_len / 2;
+#endif /* CONFIG_TESTING_OPTIONS */
+#endif /* CONFIG_DPP */
#ifdef CONFIG_TESTING_OPTIONS
} else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
wpa_s->ext_mgmt_frame_handling = !!atoi(value);
@@ -517,9 +658,54 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
wpa_s->ignore_auth_resp = !!atoi(value);
} else if (os_strcasecmp(cmd, "ignore_assoc_disallow") == 0) {
wpa_s->ignore_assoc_disallow = !!atoi(value);
+ wpa_drv_ignore_assoc_disallow(wpa_s,
+ wpa_s->ignore_assoc_disallow);
} else if (os_strcasecmp(cmd, "reject_btm_req_reason") == 0) {
wpa_s->reject_btm_req_reason = atoi(value);
+ } else if (os_strcasecmp(cmd, "get_pref_freq_list_override") == 0) {
+ os_free(wpa_s->get_pref_freq_list_override);
+ if (!value[0])
+ wpa_s->get_pref_freq_list_override = NULL;
+ else
+ wpa_s->get_pref_freq_list_override = os_strdup(value);
+ } else if (os_strcasecmp(cmd, "sae_commit_override") == 0) {
+ wpabuf_free(wpa_s->sae_commit_override);
+ if (value[0] == '\0')
+ wpa_s->sae_commit_override = NULL;
+ else
+ wpa_s->sae_commit_override = wpabuf_parse_bin(value);
+#ifdef CONFIG_DPP
+ } else if (os_strcasecmp(cmd, "dpp_config_obj_override") == 0) {
+ os_free(wpa_s->dpp_config_obj_override);
+ if (value[0] == '\0')
+ wpa_s->dpp_config_obj_override = NULL;
+ else
+ wpa_s->dpp_config_obj_override = os_strdup(value);
+ } else if (os_strcasecmp(cmd, "dpp_discovery_override") == 0) {
+ os_free(wpa_s->dpp_discovery_override);
+ if (value[0] == '\0')
+ wpa_s->dpp_discovery_override = NULL;
+ else
+ wpa_s->dpp_discovery_override = os_strdup(value);
+ } else if (os_strcasecmp(cmd, "dpp_groups_override") == 0) {
+ os_free(wpa_s->dpp_groups_override);
+ if (value[0] == '\0')
+ wpa_s->dpp_groups_override = NULL;
+ else
+ wpa_s->dpp_groups_override = os_strdup(value);
+ } else if (os_strcasecmp(cmd,
+ "dpp_ignore_netaccesskey_mismatch") == 0) {
+ wpa_s->dpp_ignore_netaccesskey_mismatch = atoi(value);
+ } else if (os_strcasecmp(cmd, "dpp_test") == 0) {
+ dpp_test = atoi(value);
+#endif /* CONFIG_DPP */
#endif /* CONFIG_TESTING_OPTIONS */
+#ifdef CONFIG_FILS
+ } else if (os_strcasecmp(cmd, "disable_fils") == 0) {
+ wpa_s->disable_fils = !!atoi(value);
+ wpa_drv_disable_fils(wpa_s, wpa_s->disable_fils);
+ wpa_supplicant_set_default_scan_ies(wpa_s);
+#endif /* CONFIG_FILS */
#ifndef CONFIG_NO_CONFIG_BLOBS
} else if (os_strcmp(cmd, "blob") == 0) {
ret = wpas_ctrl_set_blob(wpa_s, value);
@@ -529,11 +715,53 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
#ifdef CONFIG_MBO
} else if (os_strcasecmp(cmd, "non_pref_chan") == 0) {
ret = wpas_mbo_update_non_pref_chan(wpa_s, value);
+ if (ret == 0) {
+ value[-1] = '=';
+ wpa_config_process_global(wpa_s->conf, cmd, -1);
+ }
} else if (os_strcasecmp(cmd, "mbo_cell_capa") == 0) {
wpas_mbo_update_cell_capa(wpa_s, atoi(value));
+ } else if (os_strcasecmp(cmd, "oce") == 0) {
+ wpa_s->conf->oce = atoi(value);
+ if (wpa_s->conf->oce) {
+ if ((wpa_s->conf->oce & OCE_STA) &&
+ (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
+ wpa_s->enable_oce = OCE_STA;
+
+ if ((wpa_s->conf->oce & OCE_STA_CFON) &&
+ (wpa_s->drv_flags &
+ WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
+ /* TODO: Need to add STA-CFON support */
+ wpa_printf(MSG_ERROR,
+ "OCE STA-CFON feature is not yet supported");
+ return -1;
+ }
+ } else {
+ wpa_s->enable_oce = 0;
+ }
+ wpa_supplicant_set_default_scan_ies(wpa_s);
#endif /* CONFIG_MBO */
} else if (os_strcasecmp(cmd, "lci") == 0) {
ret = wpas_ctrl_iface_set_lci(wpa_s, value);
+ } else if (os_strcasecmp(cmd, "tdls_trigger_control") == 0) {
+ ret = wpa_drv_set_tdls_mode(wpa_s, atoi(value));
+ } else if (os_strcasecmp(cmd, "relative_rssi") == 0) {
+ ret = wpas_ctrl_set_relative_rssi(wpa_s, value);
+ } else if (os_strcasecmp(cmd, "relative_band_adjust") == 0) {
+ ret = wpas_ctrl_set_relative_band_adjust(wpa_s, value);
+ } else if (os_strcasecmp(cmd, "ric_ies") == 0) {
+ ret = wpas_ctrl_iface_set_ric_ies(wpa_s, value);
+ } else if (os_strcasecmp(cmd, "roaming") == 0) {
+ ret = wpa_drv_roaming(wpa_s, atoi(value), NULL);
+#ifdef CONFIG_WNM
+ } else if (os_strcasecmp(cmd, "coloc_intf_elems") == 0) {
+ struct wpabuf *elems;
+
+ elems = wpabuf_parse_bin(value);
+ if (!elems)
+ return -1;
+ wnm_set_coloc_intf_elems(wpa_s, elems);
+#endif /* CONFIG_WNM */
} else {
value[-1] = '=';
ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
@@ -579,6 +807,12 @@ static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_TESTING_GET_GTK */
} else if (os_strcmp(cmd, "tls_library") == 0) {
res = tls_get_library_version(buf, buflen);
+#ifdef CONFIG_TESTING_OPTIONS
+ } else if (os_strcmp(cmd, "anonce") == 0) {
+ return wpa_snprintf_hex(buf, buflen,
+ wpa_sm_get_anonce(wpa_s->wpa),
+ WPA_NONCE_LEN);
+#endif /* CONFIG_TESTING_OPTIONS */
} else {
res = wpa_config_get_value(cmd, wpa_s->conf, buf, buflen);
}
@@ -612,27 +846,6 @@ static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
#endif /* IEEE8021X_EAPOL */
-#ifdef CONFIG_PEERKEY
-/* MLME-STKSTART.request(peer) */
-static int wpa_supplicant_ctrl_iface_stkstart(
- struct wpa_supplicant *wpa_s, char *addr)
-{
- u8 peer[ETH_ALEN];
-
- if (hwaddr_aton(addr, peer)) {
- wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid "
- "address '%s'", addr);
- return -1;
- }
-
- wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR,
- MAC2STR(peer));
-
- return wpa_sm_stkstart(wpa_s->wpa, peer);
-}
-#endif /* CONFIG_PEERKEY */
-
-
#ifdef CONFIG_TDLS
static int wpa_supplicant_ctrl_iface_tdls_discover(
@@ -957,8 +1170,11 @@ static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
#ifdef CONFIG_AP
u8 *_p2p_dev_addr = NULL;
#endif /* CONFIG_AP */
+ char *pos;
+ int multi_ap = 0;
- if (cmd == NULL || os_strcmp(cmd, "any") == 0) {
+ if (!cmd || os_strcmp(cmd, "any") == 0 ||
+ os_strncmp(cmd, "any ", 4) == 0) {
_bssid = NULL;
#ifdef CONFIG_P2P
} else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
@@ -970,18 +1186,29 @@ static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
}
_p2p_dev_addr = p2p_dev_addr;
#endif /* CONFIG_P2P */
+ } else if (os_strncmp(cmd, "multi_ap=", 9) == 0) {
+ _bssid = NULL;
+ multi_ap = atoi(cmd + 9);
} else if (hwaddr_aton(cmd, bssid)) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
cmd);
return -1;
}
+ if (cmd) {
+ pos = os_strstr(cmd, " multi_ap=");
+ if (pos) {
+ pos += 10;
+ multi_ap = atoi(pos);
+ }
+ }
+
#ifdef CONFIG_AP
if (wpa_s->ap_iface)
return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr);
#endif /* CONFIG_AP */
- return wpas_wps_start_pbc(wpa_s, _bssid, 0);
+ return wpas_wps_start_pbc(wpa_s, _bssid, 0, multi_ap);
}
@@ -1907,6 +2134,18 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
pos += ret;
}
+ if (wpa_s->connection_set &&
+ (wpa_s->connection_ht || wpa_s->connection_vht ||
+ wpa_s->connection_he)) {
+ ret = os_snprintf(pos, end - pos,
+ "wifi_generation=%u\n",
+ wpa_s->connection_he ? 6 :
+ (wpa_s->connection_vht ? 5 : 4));
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+
#ifdef CONFIG_AP
if (wpa_s->ap_iface) {
pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
@@ -1916,6 +2155,7 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_AP */
pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
}
+#ifdef CONFIG_SME
#ifdef CONFIG_SAE
if (wpa_s->wpa_state >= WPA_ASSOCIATED &&
#ifdef CONFIG_AP
@@ -1929,6 +2169,7 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
pos += ret;
}
#endif /* CONFIG_SAE */
+#endif /* CONFIG_SME */
ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
wpa_supplicant_state_txt(wpa_s->wpa_state));
if (os_snprintf_error(end - pos, ret))
@@ -2050,6 +2291,12 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
pos += res;
}
+#ifdef CONFIG_MACSEC
+ res = ieee802_1x_kay_get_status(wpa_s->kay, pos, end - pos);
+ if (res > 0)
+ pos += res;
+#endif /* CONFIG_MACSEC */
+
sess_id = eapol_sm_get_session_id(wpa_s->eapol, &sess_id_len);
if (sess_id) {
char *start = pos;
@@ -2083,6 +2330,13 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
}
#endif /* CONFIG_WPS */
+ if (wpa_s->ieee80211ac) {
+ ret = os_snprintf(pos, end - pos, "ieee80211ac=1\n");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+
#ifdef ANDROID
/*
* Allow using the STATUS command with default behavior, say for debug,
@@ -2439,6 +2693,59 @@ static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
}
#endif /* CONFIG_SUITEB192 */
+#ifdef CONFIG_FILS
+ if (data.key_mgmt & WPA_KEY_MGMT_FILS_SHA256) {
+ ret = os_snprintf(pos, end - pos, "%sFILS-SHA256",
+ pos == start ? "" : "+");
+ if (os_snprintf_error(end - pos, ret))
+ return pos;
+ pos += ret;
+ }
+ if (data.key_mgmt & WPA_KEY_MGMT_FILS_SHA384) {
+ ret = os_snprintf(pos, end - pos, "%sFILS-SHA384",
+ pos == start ? "" : "+");
+ if (os_snprintf_error(end - pos, ret))
+ return pos;
+ pos += ret;
+ }
+#ifdef CONFIG_IEEE80211R
+ if (data.key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) {
+ ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA256",
+ pos == start ? "" : "+");
+ if (os_snprintf_error(end - pos, ret))
+ return pos;
+ pos += ret;
+ }
+ if (data.key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) {
+ ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA384",
+ pos == start ? "" : "+");
+ if (os_snprintf_error(end - pos, ret))
+ return pos;
+ pos += ret;
+ }
+#endif /* CONFIG_IEEE80211R */
+#endif /* CONFIG_FILS */
+
+#ifdef CONFIG_OWE
+ if (data.key_mgmt & WPA_KEY_MGMT_OWE) {
+ ret = os_snprintf(pos, end - pos, "%sOWE",
+ pos == start ? "" : "+");
+ if (os_snprintf_error(end - pos, ret))
+ return pos;
+ pos += ret;
+ }
+#endif /* CONFIG_OWE */
+
+#ifdef CONFIG_DPP
+ if (data.key_mgmt & WPA_KEY_MGMT_DPP) {
+ ret = os_snprintf(pos, end - pos, "%sDPP",
+ pos == start ? "" : "+");
+ if (os_snprintf_error(end - pos, ret))
+ return pos;
+ pos += ret;
+ }
+#endif /* CONFIG_DPP */
+
if (data.key_mgmt & WPA_KEY_MGMT_OSEN) {
ret = os_snprintf(pos, end - pos, "%sOSEN",
pos == start ? "" : "+");
@@ -2514,7 +2821,7 @@ static int wpa_supplicant_ctrl_iface_scan_result(
{
char *pos, *end;
int ret;
- const u8 *ie, *ie2, *osen_ie, *p2p, *mesh;
+ const u8 *ie, *ie2, *osen_ie, *p2p, *mesh, *owe;
mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID);
p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
@@ -2545,6 +2852,14 @@ static int wpa_supplicant_ctrl_iface_scan_result(
if (osen_ie)
pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
osen_ie, 2 + osen_ie[1]);
+ owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
+ if (owe) {
+ ret = os_snprintf(pos, end - pos,
+ ie2 ? "[OWE-TRANS]" : "[OWE-TRANS-OPEN]");
+ if (os_snprintf_error(end - pos, ret))
+ return -1;
+ pos += ret;
+ }
pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
if (!ie && !ie2 && !osen_ie && (bss->caps & IEEE80211_CAP_PRIVACY)) {
ret = os_snprintf(pos, end - pos, "[WEP]");
@@ -2610,6 +2925,14 @@ static int wpa_supplicant_ctrl_iface_scan_result(
pos += ret;
}
#endif /* CONFIG_HS20 */
+#ifdef CONFIG_FILS
+ if (wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION)) {
+ ret = os_snprintf(pos, end - pos, "[FILS]");
+ if (os_snprintf_error(end - pos, ret))
+ return -1;
+ pos += ret;
+ }
+#endif /* CONFIG_FILS */
#ifdef CONFIG_FST
if (wpa_bss_get_ie(bss, WLAN_EID_MULTI_BAND)) {
ret = os_snprintf(pos, end - pos, "[FST]");
@@ -2618,6 +2941,12 @@ static int wpa_supplicant_ctrl_iface_scan_result(
pos += ret;
}
#endif /* CONFIG_FST */
+ if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_UTF_8_SSID)) {
+ ret = os_snprintf(pos, end - pos, "[UTF-8]");
+ if (os_snprintf_error(end - pos, ret))
+ return -1;
+ pos += ret;
+ }
ret = os_snprintf(pos, end - pos, "\t%s",
wpa_ssid_txt(bss->ssid, bss->ssid_len));
@@ -2837,9 +3166,8 @@ static int wpa_supplicant_ctrl_iface_select_network(
if (pos) {
int *freqs = freq_range_to_channel_list(wpa_s, pos + 6);
if (freqs) {
- wpa_s->scan_req = MANUAL_SCAN_REQ;
- os_free(wpa_s->manual_scan_freqs);
- wpa_s->manual_scan_freqs = freqs;
+ os_free(wpa_s->select_network_scan_freqs);
+ wpa_s->select_network_scan_freqs = freqs;
}
}
@@ -3014,6 +3342,7 @@ static int wpa_supplicant_ctrl_iface_update_network(
return 0; /* No change to the previously configured value */
if (os_strcmp(name, "bssid") != 0 &&
+ os_strcmp(name, "bssid_hint") != 0 &&
os_strcmp(name, "priority") != 0) {
wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
@@ -3649,6 +3978,66 @@ static int ctrl_iface_get_capability_key_mgmt(int res, char *strict,
pos += ret;
}
#endif /* CONFIG_SUITEB192 */
+#ifdef CONFIG_OWE
+ if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE) {
+ ret = os_snprintf(pos, end - pos, " OWE");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+#endif /* CONFIG_OWE */
+#ifdef CONFIG_DPP
+ if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_DPP) {
+ ret = os_snprintf(pos, end - pos, " DPP");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+#endif /* CONFIG_DPP */
+#ifdef CONFIG_FILS
+ if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256) {
+ ret = os_snprintf(pos, end - pos, " FILS-SHA256");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+ if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384) {
+ ret = os_snprintf(pos, end - pos, " FILS-SHA384");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+#ifdef CONFIG_IEEE80211R
+ if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256) {
+ ret = os_snprintf(pos, end - pos, " FT-FILS-SHA256");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+ if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384) {
+ ret = os_snprintf(pos, end - pos, " FT-FILS-SHA384");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+#endif /* CONFIG_IEEE80211R */
+#endif /* CONFIG_FILS */
+#ifdef CONFIG_IEEE80211R
+ if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) {
+ ret = os_snprintf(pos, end - pos, " FT-PSK");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_SAE
+ if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) {
+ ret = os_snprintf(pos, end - pos, " SAE");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+#endif /* CONFIG_SAE */
return pos - buf;
}
@@ -3751,6 +4140,26 @@ static int ctrl_iface_get_capability_auth_alg(struct wpa_supplicant *wpa_s,
}
#endif /* CONFIG_SAE */
+#ifdef CONFIG_FILS
+ if (wpa_is_fils_supported(wpa_s)) {
+ ret = os_snprintf(pos, end - pos, "%sFILS_SK_WITHOUT_PFS",
+ pos == buf ? "" : " ");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+
+#ifdef CONFIG_FILS_SK_PFS
+ if (wpa_is_fils_sk_pfs_supported(wpa_s)) {
+ ret = os_snprintf(pos, end - pos, "%sFILS_SK_WITH_PFS",
+ pos == buf ? "" : " ");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+#endif /* CONFIG_FILS_SK_PFS */
+#endif /* CONFIG_FILS */
+
return pos - buf;
}
@@ -4008,6 +4417,47 @@ static int wpa_supplicant_ctrl_iface_get_capability(
}
#endif /* CONFIG_ACS */
+#ifdef CONFIG_FILS
+ if (os_strcmp(field, "fils") == 0) {
+#ifdef CONFIG_FILS_SK_PFS
+ if (wpa_is_fils_supported(wpa_s) &&
+ wpa_is_fils_sk_pfs_supported(wpa_s)) {
+ res = os_snprintf(buf, buflen, "FILS FILS-SK-PFS");
+ if (os_snprintf_error(buflen, res))
+ return -1;
+ return res;
+ }
+#endif /* CONFIG_FILS_SK_PFS */
+
+ if (wpa_is_fils_supported(wpa_s)) {
+ res = os_snprintf(buf, buflen, "FILS");
+ if (os_snprintf_error(buflen, res))
+ return -1;
+ return res;
+ }
+ }
+#endif /* CONFIG_FILS */
+
+ if (os_strcmp(field, "multibss") == 0 && wpa_s->multi_bss_support) {
+ res = os_snprintf(buf, buflen, "MULTIBSS-STA");
+ if (os_snprintf_error(buflen, res))
+ return -1;
+ return res;
+ }
+
+#ifdef CONFIG_DPP
+ if (os_strcmp(field, "dpp") == 0) {
+#ifdef CONFIG_DPP2
+ res = os_snprintf(buf, buflen, "DPP=2");
+#else /* CONFIG_DPP2 */
+ res = os_snprintf(buf, buflen, "DPP=1");
+#endif /* CONFIG_DPP2 */
+ if (os_snprintf_error(buflen, res))
+ return -1;
+ return res;
+ }
+#endif /* CONFIG_DPP */
+
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
field);
@@ -4050,13 +4500,85 @@ static char * anqp_add_hex(char *pos, char *end, const char *title,
#endif /* CONFIG_INTERWORKING */
+#ifdef CONFIG_FILS
+static int print_fils_indication(struct wpa_bss *bss, char *pos, char *end)
+{
+ char *start = pos;
+ const u8 *ie, *ie_end;
+ u16 info, realms;
+ int ret;
+
+ ie = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION);
+ if (!ie)
+ return 0;
+ ie_end = ie + 2 + ie[1];
+ ie += 2;
+ if (ie_end - ie < 2)
+ return -1;
+
+ info = WPA_GET_LE16(ie);
+ ie += 2;
+ ret = os_snprintf(pos, end - pos, "fils_info=%04x\n", info);
+ if (os_snprintf_error(end - pos, ret))
+ return 0;
+ pos += ret;
+
+ if (info & BIT(7)) {
+ /* Cache Identifier Included */
+ if (ie_end - ie < 2)
+ return -1;
+ ret = os_snprintf(pos, end - pos, "fils_cache_id=%02x%02x\n",
+ ie[0], ie[1]);
+ if (os_snprintf_error(end - pos, ret))
+ return 0;
+ pos += ret;
+ ie += 2;
+ }
+
+ if (info & BIT(8)) {
+ /* HESSID Included */
+ if (ie_end - ie < ETH_ALEN)
+ return -1;
+ ret = os_snprintf(pos, end - pos, "fils_hessid=" MACSTR "\n",
+ MAC2STR(ie));
+ if (os_snprintf_error(end - pos, ret))
+ return 0;
+ pos += ret;
+ ie += ETH_ALEN;
+ }
+
+ realms = (info & (BIT(3) | BIT(4) | BIT(5))) >> 3;
+ if (realms) {
+ if (ie_end - ie < realms * 2)
+ return -1;
+ ret = os_snprintf(pos, end - pos, "fils_realms=");
+ if (os_snprintf_error(end - pos, ret))
+ return 0;
+ pos += ret;
+
+ ret = wpa_snprintf_hex(pos, end - pos, ie, realms * 2);
+ if (ret <= 0)
+ return 0;
+ pos += ret;
+ ie += realms * 2;
+ ret = os_snprintf(pos, end - pos, "\n");
+ if (os_snprintf_error(end - pos, ret))
+ return 0;
+ pos += ret;
+ }
+
+ return pos - start;
+}
+#endif /* CONFIG_FILS */
+
+
static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
unsigned long mask, char *buf, size_t buflen)
{
size_t i;
int ret;
char *pos, *end;
- const u8 *ie, *ie2, *osen_ie;
+ const u8 *ie, *ie2, *osen_ie, *mesh, *owe;
pos = buf;
end = buf + buflen;
@@ -4165,18 +4687,30 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
return 0;
pos += ret;
+ mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID);
+
ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
if (ie)
pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie,
2 + ie[1]);
ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
if (ie2)
- pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2,
+ pos = wpa_supplicant_ie_txt(pos, end,
+ mesh ? "RSN" : "WPA2", ie2,
2 + ie2[1]);
osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
if (osen_ie)
pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
osen_ie, 2 + osen_ie[1]);
+ owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
+ if (owe) {
+ ret = os_snprintf(
+ pos, end - pos,
+ ie2 ? "[OWE-TRANS]" : "[OWE-TRANS-OPEN]");
+ if (os_snprintf_error(end - pos, ret))
+ return 0;
+ pos += ret;
+ }
pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
if (!ie && !ie2 && !osen_ie &&
(bss->caps & IEEE80211_CAP_PRIVACY)) {
@@ -4185,6 +4719,14 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
return 0;
pos += ret;
}
+
+ if (mesh) {
+ ret = os_snprintf(pos, end - pos, "[MESH]");
+ if (os_snprintf_error(end - pos, ret))
+ return 0;
+ pos += ret;
+ }
+
if (bss_is_dmg(bss)) {
const char *s;
ret = os_snprintf(pos, end - pos, "[DMG]");
@@ -4238,6 +4780,28 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
pos += ret;
}
#endif /* CONFIG_HS20 */
+#ifdef CONFIG_FILS
+ if (wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION)) {
+ ret = os_snprintf(pos, end - pos, "[FILS]");
+ if (os_snprintf_error(end - pos, ret))
+ return 0;
+ pos += ret;
+ }
+#endif /* CONFIG_FILS */
+#ifdef CONFIG_FST
+ if (wpa_bss_get_ie(bss, WLAN_EID_MULTI_BAND)) {
+ ret = os_snprintf(pos, end - pos, "[FST]");
+ if (os_snprintf_error(end - pos, ret))
+ return 0;
+ pos += ret;
+ }
+#endif /* CONFIG_FST */
+ if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_UTF_8_SSID)) {
+ ret = os_snprintf(pos, end - pos, "[UTF-8]");
+ if (os_snprintf_error(end - pos, ret))
+ return 0;
+ pos += ret;
+ }
ret = os_snprintf(pos, end - pos, "\n");
if (os_snprintf_error(end - pos, ret))
@@ -4322,6 +4886,8 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
pos = anqp_add_hex(pos, end, "anqp_3gpp", anqp->anqp_3gpp);
pos = anqp_add_hex(pos, end, "anqp_domain_name",
anqp->domain_name);
+ pos = anqp_add_hex(pos, end, "anqp_fils_realm_info",
+ anqp->fils_realm_info);
#ifdef CONFIG_HS20
pos = anqp_add_hex(pos, end, "hs20_capability_list",
anqp->hs20_capability_list);
@@ -4335,6 +4901,10 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
anqp->hs20_operating_class);
pos = anqp_add_hex(pos, end, "hs20_osu_providers_list",
anqp->hs20_osu_providers_list);
+ pos = anqp_add_hex(pos, end, "hs20_operator_icon_metadata",
+ anqp->hs20_operator_icon_metadata);
+ pos = anqp_add_hex(pos, end, "hs20_osu_providers_nai_list",
+ anqp->hs20_osu_providers_nai_list);
#endif /* CONFIG_HS20 */
dl_list_for_each(elem, &anqp->anqp_elems,
@@ -4383,6 +4953,44 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
}
#endif /* CONFIG_FST */
+ if (mask & WPA_BSS_MASK_UPDATE_IDX) {
+ ret = os_snprintf(pos, end - pos, "update_idx=%u\n",
+ bss->last_update_idx);
+ if (os_snprintf_error(end - pos, ret))
+ return 0;
+ pos += ret;
+ }
+
+ if ((mask & WPA_BSS_MASK_BEACON_IE) && bss->beacon_ie_len) {
+ ret = os_snprintf(pos, end - pos, "beacon_ie=");
+ if (os_snprintf_error(end - pos, ret))
+ return 0;
+ pos += ret;
+
+ ie = (const u8 *) (bss + 1);
+ ie += bss->ie_len;
+ for (i = 0; i < bss->beacon_ie_len; i++) {
+ ret = os_snprintf(pos, end - pos, "%02x", *ie++);
+ if (os_snprintf_error(end - pos, ret))
+ return 0;
+ pos += ret;
+ }
+
+ ret = os_snprintf(pos, end - pos, "\n");
+ if (os_snprintf_error(end - pos, ret))
+ return 0;
+ pos += ret;
+ }
+
+#ifdef CONFIG_FILS
+ if (mask & WPA_BSS_MASK_FILS_INDICATION) {
+ ret = print_fils_indication(bss, pos, end);
+ if (ret < 0)
+ return 0;
+ pos += ret;
+ }
+#endif /* CONFIG_FILS */
+
if (mask & WPA_BSS_MASK_DELIM) {
ret = os_snprintf(pos, end - pos, "====\n");
if (os_snprintf_error(end - pos, ret))
@@ -4473,6 +5081,8 @@ static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
bss = dl_list_entry(next, struct wpa_bss,
list_id);
}
+ } else if (os_strncmp(cmd, "CURRENT", 7) == 0) {
+ bss = wpa_s->current_bss;
#ifdef CONFIG_P2P
} else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
if (hwaddr_aton(cmd + 13, bssid) == 0)
@@ -4488,10 +5098,11 @@ static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
bss = NULL;
dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id)
{
- if (i-- == 0) {
+ if (i == 0) {
bss = tmp;
break;
}
+ i--;
}
}
@@ -4977,6 +5588,7 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
int ht40, vht, max_oper_chwidth, chwidth = 0, freq2 = 0;
u8 _group_ssid[SSID_MAX_LEN], *group_ssid = NULL;
size_t group_ssid_len = 0;
+ int he;
if (!wpa_s->global->p2p_init_wpa_s)
return -1;
@@ -4989,7 +5601,7 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
/* <addr> <"pbc" | "pin" | PIN> [label|display|keypad|p2ps]
* [persistent|persistent=<network id>]
* [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc]
- * [ht40] [vht] [auto] [ssid=<hexdump>] */
+ * [ht40] [vht] [he] [auto] [ssid=<hexdump>] */
if (hwaddr_aton(cmd, addr))
return -1;
@@ -5020,6 +5632,7 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
vht;
+ he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he;
pos2 = os_strstr(pos, " go_intent=");
if (pos2) {
@@ -5090,7 +5703,7 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
persistent_group, automatic, join,
auth, go_intent, freq, freq2, persistent_id,
- pd, ht40, vht, max_oper_chwidth,
+ pd, ht40, vht, max_oper_chwidth, he,
group_ssid, group_ssid_len);
if (new_pin == -2) {
os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
@@ -5646,7 +6259,7 @@ static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
struct wpa_ssid *ssid;
u8 *_peer = NULL, peer[ETH_ALEN];
int freq = 0, pref_freq = 0;
- int ht40, vht, max_oper_chwidth, chwidth = 0, freq2 = 0;
+ int ht40, vht, he, max_oper_chwidth, chwidth = 0, freq2 = 0;
id = atoi(cmd);
pos = os_strstr(cmd, " peer=");
@@ -5683,6 +6296,7 @@ static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
vht;
+ he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he;
pos = os_strstr(cmd, "freq2=");
if (pos)
@@ -5697,7 +6311,7 @@ static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
return -1;
return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, freq2, ht40, vht,
- max_oper_chwidth, pref_freq);
+ max_oper_chwidth, pref_freq, he);
}
@@ -5745,7 +6359,8 @@ static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
int id, int freq, int vht_center_freq2,
- int ht40, int vht, int vht_chwidth)
+ int ht40, int vht, int vht_chwidth,
+ int he)
{
struct wpa_ssid *ssid;
@@ -5759,7 +6374,7 @@ static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq,
vht_center_freq2, 0, ht40, vht,
- vht_chwidth, NULL, 0, 0);
+ vht_chwidth, he, NULL, 0, 0);
}
@@ -5768,20 +6383,31 @@ static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
int freq = 0, persistent = 0, group_id = -1;
int vht = wpa_s->conf->p2p_go_vht;
int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
+ int he = wpa_s->conf->p2p_go_he;
int max_oper_chwidth, chwidth = 0, freq2 = 0;
char *token, *context = NULL;
+#ifdef CONFIG_ACS
+ int acs = 0;
+#endif /* CONFIG_ACS */
while ((token = str_token(cmd, " ", &context))) {
- if (sscanf(token, "freq=%d", &freq) == 1 ||
- sscanf(token, "freq2=%d", &freq2) == 1 ||
+ if (sscanf(token, "freq2=%d", &freq2) == 1 ||
sscanf(token, "persistent=%d", &group_id) == 1 ||
sscanf(token, "max_oper_chwidth=%d", &chwidth) == 1) {
continue;
+#ifdef CONFIG_ACS
+ } else if (os_strcmp(token, "freq=acs") == 0) {
+ acs = 1;
+#endif /* CONFIG_ACS */
+ } else if (sscanf(token, "freq=%d", &freq) == 1) {
+ continue;
} else if (os_strcmp(token, "ht40") == 0) {
ht40 = 1;
} else if (os_strcmp(token, "vht") == 0) {
vht = 1;
ht40 = 1;
+ } else if (os_strcmp(token, "he") == 0) {
+ he = 1;
} else if (os_strcmp(token, "persistent") == 0) {
persistent = 1;
} else {
@@ -5792,6 +6418,26 @@ static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
}
}
+#ifdef CONFIG_ACS
+ if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) &&
+ (acs || freq == 2 || freq == 5)) {
+ if (freq == 2 && wpa_s->best_24_freq <= 0) {
+ wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211G;
+ wpa_s->p2p_go_do_acs = 1;
+ freq = 0;
+ } else if (freq == 5 && wpa_s->best_5_freq <= 0) {
+ wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211A;
+ wpa_s->p2p_go_do_acs = 1;
+ freq = 0;
+ } else {
+ wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211ANY;
+ wpa_s->p2p_go_do_acs = 1;
+ }
+ } else {
+ wpa_s->p2p_go_do_acs = 0;
+ }
+#endif /* CONFIG_ACS */
+
max_oper_chwidth = parse_freq(chwidth, freq2);
if (max_oper_chwidth < 0)
return -1;
@@ -5799,10 +6445,10 @@ static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
if (group_id >= 0)
return p2p_ctrl_group_add_persistent(wpa_s, group_id,
freq, freq2, ht40, vht,
- max_oper_chwidth);
+ max_oper_chwidth, he);
return wpas_p2p_group_add(wpa_s, persistent, freq, freq2, ht40, vht,
- max_oper_chwidth);
+ max_oper_chwidth, he);
}
@@ -5829,10 +6475,24 @@ static int p2p_ctrl_group_member(struct wpa_supplicant *wpa_s, const char *cmd,
}
+static int wpas_find_p2p_dev_addr_bss(struct wpa_global *global,
+ const u8 *p2p_dev_addr)
+{
+ struct wpa_supplicant *wpa_s;
+
+ for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
+ if (wpa_bss_get_p2p_dev_addr(wpa_s, p2p_dev_addr))
+ return 1;
+ }
+
+ return 0;
+}
+
+
static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
char *buf, size_t buflen)
{
- u8 addr[ETH_ALEN], *addr_ptr;
+ u8 addr[ETH_ALEN], *addr_ptr, group_capab;
int next, res;
const struct p2p_peer_info *info;
char *pos, *end;
@@ -5861,6 +6521,16 @@ static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next);
if (info == NULL)
return -1;
+ group_capab = info->group_capab;
+
+ if (group_capab &&
+ !wpas_find_p2p_dev_addr_bss(wpa_s->global, info->p2p_device_addr)) {
+ wpa_printf(MSG_DEBUG,
+ "P2P: Could not find any BSS with p2p_dev_addr "
+ MACSTR ", hence override group_capab from 0x%x to 0",
+ MAC2STR(info->p2p_device_addr), group_capab);
+ group_capab = 0;
+ }
pos = buf;
end = buf + buflen;
@@ -5886,7 +6556,7 @@ static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
info->serial_number,
info->config_methods,
info->dev_capab,
- info->group_capab,
+ group_capab,
info->level);
if (os_snprintf_error(end - pos, res))
return pos - buf;
@@ -6167,6 +6837,20 @@ static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
return 0;
}
+ if (os_strcmp(cmd, "override_pref_op_chan") == 0) {
+ int op_class, chan;
+
+ op_class = atoi(param);
+ param = os_strchr(param, ':');
+ if (!param)
+ return -1;
+ param++;
+ chan = atoi(param);
+ p2p_set_override_pref_op_chan(wpa_s->global->p2p, op_class,
+ chan);
+ return 0;
+ }
+
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
cmd);
@@ -6178,6 +6862,12 @@ static void p2p_ctrl_flush(struct wpa_supplicant *wpa_s)
{
os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
wpa_s->force_long_sd = 0;
+
+#ifdef CONFIG_TESTING_OPTIONS
+ os_free(wpa_s->get_pref_freq_list_override);
+ wpa_s->get_pref_freq_list_override = NULL;
+#endif /* CONFIG_TESTING_OPTIONS */
+
wpas_p2p_stop_find(wpa_s);
wpa_s->parent->p2ps_method_config_any = 0;
if (wpa_s->global->p2p)
@@ -6385,7 +7075,7 @@ static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
u16 id[MAX_ANQP_INFO_ID];
size_t num_id = 0;
u32 subtypes = 0;
- int get_cell_pref = 0;
+ u32 mbo_subtypes = 0;
used = hwaddr_aton2(dst, dst_addr);
if (used < 0)
@@ -6406,9 +7096,10 @@ static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
} else if (os_strncmp(pos, "mbo:", 4) == 0) {
#ifdef CONFIG_MBO
int num = atoi(pos + 4);
- if (num != MBO_ANQP_SUBTYPE_CELL_CONN_PREF)
+
+ if (num <= 0 || num > MAX_MBO_ANQP_SUBTYPE)
return -1;
- get_cell_pref = 1;
+ mbo_subtypes |= BIT(num);
#else /* CONFIG_MBO */
return -1;
#endif /* CONFIG_MBO */
@@ -6423,11 +7114,11 @@ static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
pos++;
}
- if (num_id == 0)
+ if (num_id == 0 && !subtypes && !mbo_subtypes)
return -1;
return anqp_send_req(wpa_s, dst_addr, id, num_id, subtypes,
- get_cell_pref);
+ mbo_subtypes);
}
@@ -6764,6 +7455,9 @@ static int wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant *wpa_s,
autoscan_init(wpa_s, 1);
else if (state == WPA_SCANNING)
wpa_supplicant_reinit_autoscan(wpa_s);
+ else
+ wpa_printf(MSG_DEBUG, "No autoscan update in state %s",
+ wpa_supplicant_state_txt(state));
return 0;
}
@@ -6826,26 +7520,41 @@ static int wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant *wpa_s, char *cmd)
static int wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant *wpa_s, char *cmd)
{
int query_reason, list = 0;
+ char *btm_candidates = NULL;
query_reason = atoi(cmd);
cmd = os_strchr(cmd, ' ');
if (cmd) {
- cmd++;
- if (os_strncmp(cmd, "list", 4) == 0) {
+ if (os_strncmp(cmd, " list", 5) == 0)
list = 1;
- } else {
- wpa_printf(MSG_DEBUG, "WNM Query: Invalid option %s",
- cmd);
- return -1;
- }
+ else
+ btm_candidates = cmd;
}
wpa_printf(MSG_DEBUG,
"CTRL_IFACE: WNM_BSS_QUERY query_reason=%d%s",
query_reason, list ? " candidate list" : "");
- return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason, list);
+ return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason,
+ btm_candidates,
+ list);
+}
+
+
+static int wpas_ctrl_iface_coloc_intf_report(struct wpa_supplicant *wpa_s,
+ char *cmd)
+{
+ struct wpabuf *elems;
+ int ret;
+
+ elems = wpabuf_parse_bin(cmd);
+ if (!elems)
+ return -1;
+
+ ret = wnm_send_coloc_intf_report(wpa_s, 0, elems);
+ wpabuf_free(elems);
+ return ret;
}
#endif /* CONFIG_WNM */
@@ -6881,10 +7590,17 @@ static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
pos += ret;
}
- if (si.center_frq1 > 0 && si.center_frq2 > 0) {
- ret = os_snprintf(pos, end - pos,
- "CENTER_FRQ1=%d\nCENTER_FRQ2=%d\n",
- si.center_frq1, si.center_frq2);
+ if (si.center_frq1 > 0) {
+ ret = os_snprintf(pos, end - pos, "CENTER_FRQ1=%d\n",
+ si.center_frq1);
+ if (os_snprintf_error(end - pos, ret))
+ return -1;
+ pos += ret;
+ }
+
+ if (si.center_frq2 > 0) {
+ ret = os_snprintf(pos, end - pos, "CENTER_FRQ2=%d\n",
+ si.center_frq2);
if (os_snprintf_error(end - pos, ret))
return -1;
pos += ret;
@@ -6932,6 +7648,46 @@ static int wpas_ctrl_iface_signal_monitor(struct wpa_supplicant *wpa_s,
}
+#ifdef CONFIG_TESTING_OPTIONS
+int wpas_ctrl_iface_get_pref_freq_list_override(struct wpa_supplicant *wpa_s,
+ enum wpa_driver_if_type if_type,
+ unsigned int *num,
+ unsigned int *freq_list)
+{
+ char *pos = wpa_s->get_pref_freq_list_override;
+ char *end;
+ unsigned int count = 0;
+
+ /* Override string format:
+ * <if_type1>:<freq1>,<freq2>,... <if_type2>:... */
+
+ while (pos) {
+ if (atoi(pos) == (int) if_type)
+ break;
+ pos = os_strchr(pos, ' ');
+ if (pos)
+ pos++;
+ }
+ if (!pos)
+ return -1;
+ pos = os_strchr(pos, ':');
+ if (!pos)
+ return -1;
+ pos++;
+ end = os_strchr(pos, ' ');
+ while (pos && (!end || pos < end) && count < *num) {
+ freq_list[count++] = atoi(pos);
+ pos = os_strchr(pos, ',');
+ if (pos)
+ pos++;
+ }
+
+ *num = count;
+ return 0;
+}
+#endif /* CONFIG_TESTING_OPTIONS */
+
+
static int wpas_ctrl_iface_get_pref_freq_list(
struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
{
@@ -6961,7 +7717,7 @@ static int wpas_ctrl_iface_get_pref_freq_list(
wpa_printf(MSG_DEBUG,
"CTRL_IFACE: GET_PREF_FREQ_LIST iface_type=%d (%s)",
- iface_type, buf);
+ iface_type, cmd);
ret = wpa_drv_get_pref_freq_list(wpa_s, iface_type, &num, freq_list);
if (ret)
@@ -7118,7 +7874,8 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
wpa_dbg(wpa_s, MSG_DEBUG, "Flush all wpa_supplicant state");
- wpas_abort_ongoing_scan(wpa_s);
+ if (wpas_abort_ongoing_scan(wpa_s) == 0)
+ wpa_s->ignore_post_flush_scan_res = 1;
if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
/*
@@ -7159,6 +7916,22 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
wpa_s->after_wps = 0;
wpa_s->known_wps_freq = 0;
+#ifdef CONFIG_DPP
+ wpas_dpp_deinit(wpa_s);
+ wpa_s->dpp_init_max_tries = 0;
+ wpa_s->dpp_init_retry_time = 0;
+ wpa_s->dpp_resp_wait_time = 0;
+ wpa_s->dpp_resp_max_tries = 0;
+ wpa_s->dpp_resp_retry_time = 0;
+#ifdef CONFIG_TESTING_OPTIONS
+ os_memset(dpp_pkex_own_mac_override, 0, ETH_ALEN);
+ os_memset(dpp_pkex_peer_mac_override, 0, ETH_ALEN);
+ dpp_pkex_ephemeral_key_override_len = 0;
+ dpp_protocol_key_override_len = 0;
+ dpp_nonce_override_len = 0;
+#endif /* CONFIG_TESTING_OPTIONS */
+#endif /* CONFIG_DPP */
+
#ifdef CONFIG_TDLS
#ifdef CONFIG_TDLS_TESTING
tdls_testing = 0;
@@ -7220,13 +7993,29 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
wpa_s->p2p_go_csa_on_inv = 0;
wpa_s->ignore_auth_resp = 0;
wpa_s->ignore_assoc_disallow = 0;
+ wpa_s->testing_resend_assoc = 0;
wpa_s->reject_btm_req_reason = 0;
wpa_sm_set_test_assoc_ie(wpa_s->wpa, NULL);
+ os_free(wpa_s->get_pref_freq_list_override);
+ wpa_s->get_pref_freq_list_override = NULL;
+ wpabuf_free(wpa_s->sae_commit_override);
+ wpa_s->sae_commit_override = NULL;
+#ifdef CONFIG_DPP
+ os_free(wpa_s->dpp_config_obj_override);
+ wpa_s->dpp_config_obj_override = NULL;
+ os_free(wpa_s->dpp_discovery_override);
+ wpa_s->dpp_discovery_override = NULL;
+ os_free(wpa_s->dpp_groups_override);
+ wpa_s->dpp_groups_override = NULL;
+ dpp_test = DPP_TEST_DISABLED;
+#endif /* CONFIG_DPP */
#endif /* CONFIG_TESTING_OPTIONS */
wpa_s->disconnected = 0;
os_free(wpa_s->next_scan_freqs);
wpa_s->next_scan_freqs = NULL;
+ os_free(wpa_s->select_network_scan_freqs);
+ wpa_s->select_network_scan_freqs = NULL;
wpa_bss_flush(wpa_s);
if (!dl_list_empty(&wpa_s->bss)) {
@@ -7244,6 +8033,13 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
#ifdef CONFIG_SME
wpa_s->sme.last_unprot_disconnect.sec = 0;
#endif /* CONFIG_SME */
+
+ wpabuf_free(wpa_s->ric_ies);
+ wpa_s->ric_ies = NULL;
+
+ wpa_supplicant_update_channel_list(wpa_s, NULL);
+
+ free_bss_tmp_disallowed(wpa_s);
}
@@ -7541,6 +8337,19 @@ static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params,
goto done;
}
+ pos = os_strstr(params, "bssid=");
+ if (pos) {
+ u8 bssid[ETH_ALEN];
+
+ pos += 6;
+ if (hwaddr_aton(pos, bssid)) {
+ wpa_printf(MSG_ERROR, "Invalid BSSID %s", pos);
+ *reply_len = -1;
+ goto done;
+ }
+ os_memcpy(wpa_s->next_scan_bssid, bssid, ETH_ALEN);
+ }
+
pos = params;
while (pos && *pos != '\0') {
if (os_strncmp(pos, "ssid ", 5) == 0) {
@@ -7826,6 +8635,124 @@ static int wpas_ctrl_iface_mgmt_rx_process(struct wpa_supplicant *wpa_s,
}
+static int wpas_ctrl_iface_driver_scan_res(struct wpa_supplicant *wpa_s,
+ char *param)
+{
+ struct wpa_scan_res *res;
+ struct os_reltime now;
+ char *pos, *end;
+ int ret = -1;
+
+ if (!param)
+ return -1;
+
+ if (os_strcmp(param, "START") == 0) {
+ wpa_bss_update_start(wpa_s);
+ return 0;
+ }
+
+ if (os_strcmp(param, "END") == 0) {
+ wpa_bss_update_end(wpa_s, NULL, 1);
+ return 0;
+ }
+
+ if (os_strncmp(param, "BSS ", 4) != 0)
+ return -1;
+ param += 3;
+
+ res = os_zalloc(sizeof(*res) + os_strlen(param) / 2);
+ if (!res)
+ return -1;
+
+ pos = os_strstr(param, " flags=");
+ if (pos)
+ res->flags = strtol(pos + 7, NULL, 16);
+
+ pos = os_strstr(param, " bssid=");
+ if (pos && hwaddr_aton(pos + 7, res->bssid))
+ goto fail;
+
+ pos = os_strstr(param, " freq=");
+ if (pos)
+ res->freq = atoi(pos + 6);
+
+ pos = os_strstr(param, " beacon_int=");
+ if (pos)
+ res->beacon_int = atoi(pos + 12);
+
+ pos = os_strstr(param, " caps=");
+ if (pos)
+ res->caps = strtol(pos + 6, NULL, 16);
+
+ pos = os_strstr(param, " qual=");
+ if (pos)
+ res->qual = atoi(pos + 6);
+
+ pos = os_strstr(param, " noise=");
+ if (pos)
+ res->noise = atoi(pos + 7);
+
+ pos = os_strstr(param, " level=");
+ if (pos)
+ res->level = atoi(pos + 7);
+
+ pos = os_strstr(param, " tsf=");
+ if (pos)
+ res->tsf = strtoll(pos + 5, NULL, 16);
+
+ pos = os_strstr(param, " age=");
+ if (pos)
+ res->age = atoi(pos + 5);
+
+ pos = os_strstr(param, " est_throughput=");
+ if (pos)
+ res->est_throughput = atoi(pos + 16);
+
+ pos = os_strstr(param, " snr=");
+ if (pos)
+ res->snr = atoi(pos + 5);
+
+ pos = os_strstr(param, " parent_tsf=");
+ if (pos)
+ res->parent_tsf = strtoll(pos + 7, NULL, 16);
+
+ pos = os_strstr(param, " tsf_bssid=");
+ if (pos && hwaddr_aton(pos + 11, res->tsf_bssid))
+ goto fail;
+
+ pos = os_strstr(param, " ie=");
+ if (pos) {
+ pos += 4;
+ end = os_strchr(pos, ' ');
+ if (!end)
+ end = pos + os_strlen(pos);
+ res->ie_len = (end - pos) / 2;
+ if (hexstr2bin(pos, (u8 *) (res + 1), res->ie_len))
+ goto fail;
+ }
+
+ pos = os_strstr(param, " beacon_ie=");
+ if (pos) {
+ pos += 11;
+ end = os_strchr(pos, ' ');
+ if (!end)
+ end = pos + os_strlen(pos);
+ res->beacon_ie_len = (end - pos) / 2;
+ if (hexstr2bin(pos, ((u8 *) (res + 1)) + res->ie_len,
+ res->beacon_ie_len))
+ goto fail;
+ }
+
+ os_get_reltime(&now);
+ wpa_bss_update_scan_res(wpa_s, res, &now);
+ ret = 0;
+fail:
+ os_free(res);
+
+ return ret;
+}
+
+
static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd)
{
char *pos, *param;
@@ -7856,6 +8783,8 @@ static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd)
wpa_supplicant_event(wpa_s, ev, &event);
os_free(event.freq_range.range);
return 0;
+ } else if (os_strcmp(cmd, "SCAN_RES") == 0) {
+ return wpas_ctrl_iface_driver_scan_res(wpa_s, param);
} else {
wpa_dbg(wpa_s, MSG_DEBUG, "Testing - unknown driver event: %s",
cmd);
@@ -7933,26 +8862,39 @@ static void wpas_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
struct iphdr ip;
const u8 *pos;
unsigned int i;
+ char extra[30];
- if (len != HWSIM_PACKETLEN)
+ if (len < sizeof(*eth) + sizeof(ip) || len > HWSIM_PACKETLEN) {
+ wpa_printf(MSG_DEBUG,
+ "test data: RX - ignore unexpected length %d",
+ (int) len);
return;
+ }
eth = (const struct ether_header *) buf;
os_memcpy(&ip, eth + 1, sizeof(ip));
pos = &buf[sizeof(*eth) + sizeof(ip)];
if (ip.ihl != 5 || ip.version != 4 ||
- ntohs(ip.tot_len) != HWSIM_IP_LEN)
+ ntohs(ip.tot_len) > HWSIM_IP_LEN) {
+ wpa_printf(MSG_DEBUG,
+ "test data: RX - ignore unexpect IP header");
return;
+ }
- for (i = 0; i < HWSIM_IP_LEN - sizeof(ip); i++) {
- if (*pos != (u8) i)
+ for (i = 0; i < ntohs(ip.tot_len) - sizeof(ip); i++) {
+ if (*pos != (u8) i) {
+ wpa_printf(MSG_DEBUG,
+ "test data: RX - ignore mismatching payload");
return;
+ }
pos++;
}
-
- wpa_msg(wpa_s, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR,
- MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost));
+ extra[0] = '\0';
+ if (ntohs(ip.tot_len) != HWSIM_IP_LEN)
+ os_snprintf(extra, sizeof(extra), " len=%d", ntohs(ip.tot_len));
+ wpa_msg(wpa_s, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR "%s",
+ MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost), extra);
}
@@ -7996,7 +8938,7 @@ static int wpas_ctrl_iface_data_test_config(struct wpa_supplicant *wpa_s,
static int wpas_ctrl_iface_data_test_tx(struct wpa_supplicant *wpa_s, char *cmd)
{
u8 dst[ETH_ALEN], src[ETH_ALEN];
- char *pos;
+ char *pos, *pos2;
int used;
long int val;
u8 tos;
@@ -8005,11 +8947,12 @@ static int wpas_ctrl_iface_data_test_tx(struct wpa_supplicant *wpa_s, char *cmd)
struct iphdr *ip;
u8 *dpos;
unsigned int i;
+ size_t send_len = HWSIM_IP_LEN;
if (wpa_s->l2_test == NULL)
return -1;
- /* format: <dst> <src> <tos> */
+ /* format: <dst> <src> <tos> [len=<length>] */
pos = cmd;
used = hwaddr_aton2(pos, dst);
@@ -8023,11 +8966,19 @@ static int wpas_ctrl_iface_data_test_tx(struct wpa_supplicant *wpa_s, char *cmd)
return -1;
pos += used;
- val = strtol(pos, NULL, 0);
+ val = strtol(pos, &pos2, 0);
if (val < 0 || val > 0xff)
return -1;
tos = val;
+ pos = os_strstr(pos2, " len=");
+ if (pos) {
+ i = atoi(pos + 5);
+ if (i < sizeof(*ip) || i > HWSIM_IP_LEN)
+ return -1;
+ send_len = i;
+ }
+
eth = (struct ether_header *) &buf[2];
os_memcpy(eth->ether_dhost, dst, ETH_ALEN);
os_memcpy(eth->ether_shost, src, ETH_ALEN);
@@ -8038,17 +8989,17 @@ static int wpas_ctrl_iface_data_test_tx(struct wpa_supplicant *wpa_s, char *cmd)
ip->version = 4;
ip->ttl = 64;
ip->tos = tos;
- ip->tot_len = htons(HWSIM_IP_LEN);
+ ip->tot_len = htons(send_len);
ip->protocol = 1;
ip->saddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1);
ip->daddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2);
ip->check = ipv4_hdr_checksum(ip, sizeof(*ip));
dpos = (u8 *) (ip + 1);
- for (i = 0; i < HWSIM_IP_LEN - sizeof(*ip); i++)
+ for (i = 0; i < send_len - sizeof(*ip); i++)
*dpos++ = i;
if (l2_packet_send(wpa_s->l2_test, dst, ETHERTYPE_IP, &buf[2],
- HWSIM_PACKETLEN) < 0)
+ sizeof(struct ether_header) + send_len) < 0)
return -1;
wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX dst=" MACSTR " src=" MACSTR
@@ -8220,6 +9171,79 @@ static int wpas_ctrl_test_assoc_ie(struct wpa_supplicant *wpa_s,
return 0;
}
+
+static int wpas_ctrl_reset_pn(struct wpa_supplicant *wpa_s)
+{
+ u8 zero[WPA_TK_MAX_LEN];
+
+ if (wpa_s->last_tk_alg == WPA_ALG_NONE)
+ return -1;
+
+ wpa_printf(MSG_INFO, "TESTING: Reset PN");
+ os_memset(zero, 0, sizeof(zero));
+
+ /* First, use a zero key to avoid any possible duplicate key avoidance
+ * in the driver. */
+ if (wpa_drv_set_key(wpa_s, wpa_s->last_tk_alg, wpa_s->last_tk_addr,
+ wpa_s->last_tk_key_idx, 1, zero, 6,
+ zero, wpa_s->last_tk_len) < 0)
+ return -1;
+
+ /* Set the previously configured key to reset its TSC/RSC */
+ return wpa_drv_set_key(wpa_s, wpa_s->last_tk_alg, wpa_s->last_tk_addr,
+ wpa_s->last_tk_key_idx, 1, zero, 6,
+ wpa_s->last_tk, wpa_s->last_tk_len);
+}
+
+
+static int wpas_ctrl_key_request(struct wpa_supplicant *wpa_s, const char *cmd)
+{
+ const char *pos = cmd;
+ int error, pairwise;
+
+ error = atoi(pos);
+ pos = os_strchr(pos, ' ');
+ if (!pos)
+ return -1;
+ pairwise = atoi(pos);
+ wpa_sm_key_request(wpa_s->wpa, error, pairwise);
+ return 0;
+}
+
+
+static int wpas_ctrl_resend_assoc(struct wpa_supplicant *wpa_s)
+{
+#ifdef CONFIG_SME
+ struct wpa_driver_associate_params params;
+ int ret;
+
+ os_memset(&params, 0, sizeof(params));
+ params.bssid = wpa_s->bssid;
+ params.ssid = wpa_s->sme.ssid;
+ params.ssid_len = wpa_s->sme.ssid_len;
+ params.freq.freq = wpa_s->sme.freq;
+ if (wpa_s->last_assoc_req_wpa_ie) {
+ params.wpa_ie = wpabuf_head(wpa_s->last_assoc_req_wpa_ie);
+ params.wpa_ie_len = wpabuf_len(wpa_s->last_assoc_req_wpa_ie);
+ }
+ params.pairwise_suite = wpa_s->pairwise_cipher;
+ params.group_suite = wpa_s->group_cipher;
+ params.mgmt_group_suite = wpa_s->mgmt_group_cipher;
+ params.key_mgmt_suite = wpa_s->key_mgmt;
+ params.wpa_proto = wpa_s->wpa_proto;
+ params.mgmt_frame_protection = wpa_s->sme.mfp;
+ params.rrm_used = wpa_s->rrm.rrm_used;
+ if (wpa_s->sme.prev_bssid_set)
+ params.prev_bssid = wpa_s->sme.prev_bssid;
+ wpa_printf(MSG_INFO, "TESTING: Resend association request");
+ ret = wpa_drv_associate(wpa_s, &params);
+ wpa_s->testing_resend_assoc = 1;
+ return ret;
+#else /* CONFIG_SME */
+ return -1;
+#endif /* CONFIG_SME */
+}
+
#endif /* CONFIG_TESTING_OPTIONS */
@@ -8555,13 +9579,6 @@ static int wpas_ctrl_iface_mac_rand_scan(struct wpa_supplicant *wpa_s,
return -1;
}
- if ((wpa_s->mac_addr_rand_supported & type) != type) {
- wpa_printf(MSG_INFO,
- "CTRL: MAC_RAND_SCAN types=%u != supported=%u",
- type, wpa_s->mac_addr_rand_supported);
- return -1;
- }
-
if (enable > 1) {
wpa_printf(MSG_INFO,
"CTRL: MAC_RAND_SCAN enable=<0/1> not specified");
@@ -8595,21 +9612,25 @@ static int wpas_ctrl_iface_mac_rand_scan(struct wpa_supplicant *wpa_s,
}
if (type & MAC_ADDR_RAND_SCAN) {
- wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
- addr, mask);
+ if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
+ addr, mask))
+ return -1;
}
if (type & MAC_ADDR_RAND_SCHED_SCAN) {
- wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
- addr, mask);
+ if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
+ addr, mask))
+ return -1;
if (wpa_s->sched_scanning && !wpa_s->pno)
wpas_scan_restart_sched_scan(wpa_s);
}
if (type & MAC_ADDR_RAND_PNO) {
- wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
- addr, mask);
+ if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
+ addr, mask))
+ return -1;
+
if (wpa_s->pno) {
wpas_stop_pno(wpa_s);
wpas_start_pno(wpa_s);
@@ -8643,6 +9664,248 @@ static void wpas_ctrl_iface_pmksa_flush(struct wpa_supplicant *wpa_s)
}
+#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
+
+static int wpas_ctrl_iface_pmksa_get(struct wpa_supplicant *wpa_s,
+ const char *cmd, char *buf, size_t buflen)
+{
+ struct rsn_pmksa_cache_entry *entry;
+ struct wpa_ssid *ssid;
+ char *pos, *pos2, *end;
+ int ret;
+ struct os_reltime now;
+
+ ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
+ if (!ssid)
+ return -1;
+
+ pos = buf;
+ end = buf + buflen;
+
+ os_get_reltime(&now);
+
+ /*
+ * Entry format:
+ * <BSSID> <PMKID> <PMK> <reauth_time in seconds>
+ * <expiration in seconds> <akmp> <opportunistic>
+ * [FILS Cache Identifier]
+ */
+
+ for (entry = wpa_sm_pmksa_cache_head(wpa_s->wpa); entry;
+ entry = entry->next) {
+ if (entry->network_ctx != ssid)
+ continue;
+
+ pos2 = pos;
+ ret = os_snprintf(pos2, end - pos2, MACSTR " ",
+ MAC2STR(entry->aa));
+ if (os_snprintf_error(end - pos2, ret))
+ break;
+ pos2 += ret;
+
+ pos2 += wpa_snprintf_hex(pos2, end - pos2, entry->pmkid,
+ PMKID_LEN);
+
+ ret = os_snprintf(pos2, end - pos2, " ");
+ if (os_snprintf_error(end - pos2, ret))
+ break;
+ pos2 += ret;
+
+ pos2 += wpa_snprintf_hex(pos2, end - pos2, entry->pmk,
+ entry->pmk_len);
+
+ ret = os_snprintf(pos2, end - pos2, " %d %d %d %d",
+ (int) (entry->reauth_time - now.sec),
+ (int) (entry->expiration - now.sec),
+ entry->akmp,
+ entry->opportunistic);
+ if (os_snprintf_error(end - pos2, ret))
+ break;
+ pos2 += ret;
+
+ if (entry->fils_cache_id_set) {
+ ret = os_snprintf(pos2, end - pos2, " %02x%02x",
+ entry->fils_cache_id[0],
+ entry->fils_cache_id[1]);
+ if (os_snprintf_error(end - pos2, ret))
+ break;
+ pos2 += ret;
+ }
+
+ ret = os_snprintf(pos2, end - pos2, "\n");
+ if (os_snprintf_error(end - pos2, ret))
+ break;
+ pos2 += ret;
+
+ pos = pos2;
+ }
+
+ return pos - buf;
+}
+
+
+static int wpas_ctrl_iface_pmksa_add(struct wpa_supplicant *wpa_s,
+ char *cmd)
+{
+ struct rsn_pmksa_cache_entry *entry;
+ struct wpa_ssid *ssid;
+ char *pos, *pos2;
+ int ret = -1;
+ struct os_reltime now;
+ int reauth_time = 0, expiration = 0, i;
+
+ /*
+ * Entry format:
+ * <network_id> <BSSID> <PMKID> <PMK> <reauth_time in seconds>
+ * <expiration in seconds> <akmp> <opportunistic>
+ * [FILS Cache Identifier]
+ */
+
+ ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
+ if (!ssid)
+ return -1;
+
+ pos = os_strchr(cmd, ' ');
+ if (!pos)
+ return -1;
+ pos++;
+
+ entry = os_zalloc(sizeof(*entry));
+ if (!entry)
+ return -1;
+
+ if (hwaddr_aton(pos, entry->aa))
+ goto fail;
+
+ pos = os_strchr(pos, ' ');
+ if (!pos)
+ goto fail;
+ pos++;
+
+ if (hexstr2bin(pos, entry->pmkid, PMKID_LEN) < 0)
+ goto fail;
+
+ pos = os_strchr(pos, ' ');
+ if (!pos)
+ goto fail;
+ pos++;
+
+ pos2 = os_strchr(pos, ' ');
+ if (!pos2)
+ goto fail;
+ entry->pmk_len = (pos2 - pos) / 2;
+ if (entry->pmk_len < PMK_LEN || entry->pmk_len > PMK_LEN_MAX ||
+ hexstr2bin(pos, entry->pmk, entry->pmk_len) < 0)
+ goto fail;
+
+ pos = os_strchr(pos, ' ');
+ if (!pos)
+ goto fail;
+ pos++;
+
+ if (sscanf(pos, "%d %d %d %d", &reauth_time, &expiration,
+ &entry->akmp, &entry->opportunistic) != 4)
+ goto fail;
+ for (i = 0; i < 4; i++) {
+ pos = os_strchr(pos, ' ');
+ if (!pos) {
+ if (i < 3)
+ goto fail;
+ break;
+ }
+ pos++;
+ }
+ if (pos) {
+ if (hexstr2bin(pos, entry->fils_cache_id,
+ FILS_CACHE_ID_LEN) < 0)
+ goto fail;
+ entry->fils_cache_id_set = 1;
+ }
+ os_get_reltime(&now);
+ entry->expiration = now.sec + expiration;
+ entry->reauth_time = now.sec + reauth_time;
+
+ entry->network_ctx = ssid;
+
+ wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
+ entry = NULL;
+ ret = 0;
+fail:
+ os_free(entry);
+ return ret;
+}
+
+
+#ifdef CONFIG_MESH
+
+static int wpas_ctrl_iface_mesh_pmksa_get(struct wpa_supplicant *wpa_s,
+ const char *cmd, char *buf,
+ size_t buflen)
+{
+ u8 spa[ETH_ALEN];
+
+ if (!wpa_s->ifmsh)
+ return -1;
+
+ if (os_strcasecmp(cmd, "any") == 0)
+ return wpas_ap_pmksa_cache_list_mesh(wpa_s, NULL, buf, buflen);
+
+ if (hwaddr_aton(cmd, spa))
+ return -1;
+
+ return wpas_ap_pmksa_cache_list_mesh(wpa_s, spa, buf, buflen);
+}
+
+
+static int wpas_ctrl_iface_mesh_pmksa_add(struct wpa_supplicant *wpa_s,
+ char *cmd)
+{
+ /*
+ * We do not check mesh interface existance because PMKSA should be
+ * stored before wpa_s->ifmsh creation to suppress commit message
+ * creation.
+ */
+ return wpas_ap_pmksa_cache_add_external(wpa_s, cmd);
+}
+
+#endif /* CONFIG_MESH */
+#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
+
+
+#ifdef CONFIG_FILS
+static int wpas_ctrl_iface_fils_hlp_req_add(struct wpa_supplicant *wpa_s,
+ const char *cmd)
+{
+ struct fils_hlp_req *req;
+ const char *pos;
+
+ /* format: <dst> <packet starting from ethertype> */
+
+ req = os_zalloc(sizeof(*req));
+ if (!req)
+ return -1;
+
+ if (hwaddr_aton(cmd, req->dst))
+ goto fail;
+
+ pos = os_strchr(cmd, ' ');
+ if (!pos)
+ goto fail;
+ pos++;
+ req->pkt = wpabuf_parse_bin(pos);
+ if (!req->pkt)
+ goto fail;
+
+ dl_list_add_tail(&wpa_s->fils_hlp_req, &req->list);
+ return 0;
+fail:
+ wpabuf_free(req->pkt);
+ os_free(req);
+ return -1;
+}
+#endif /* CONFIG_FILS */
+
+
static int wpas_ctrl_cmd_debug_level(const char *cmd)
{
if (os_strcmp(cmd, "PING") == 0 ||
@@ -8664,7 +9927,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
int reply_len;
if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
- os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
+ os_strncmp(buf, "SET_NETWORK ", 12) == 0 ||
+ os_strncmp(buf, "PMKSA_ADD ", 10) == 0 ||
+ os_strncmp(buf, "MESH_PMKSA_ADD ", 15) == 0) {
if (wpa_debug_show_keys)
wpa_dbg(wpa_s, MSG_DEBUG,
"Control interface command '%s'", buf);
@@ -8673,7 +9938,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
"Control interface command '%s [REMOVED]'",
os_strncmp(buf, WPA_CTRL_RSP,
os_strlen(WPA_CTRL_RSP)) == 0 ?
- WPA_CTRL_RSP : "SET_NETWORK");
+ WPA_CTRL_RSP :
+ (os_strncmp(buf, "SET_NETWORK ", 12) == 0 ?
+ "SET_NETWORK" : "key-add"));
} else if (os_strncmp(buf, "WPS_NFC_TAG_READ", 16) == 0 ||
os_strncmp(buf, "NFC_REPORT_HANDOVER", 19) == 0) {
wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
@@ -8709,6 +9976,11 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
reply_len += eapol_sm_get_mib(wpa_s->eapol,
reply + reply_len,
reply_size - reply_len);
+#ifdef CONFIG_MACSEC
+ reply_len += ieee802_1x_kay_get_mib(
+ wpa_s->kay, reply + reply_len,
+ reply_size - reply_len);
+#endif /* CONFIG_MACSEC */
}
} else if (os_strncmp(buf, "STATUS", 6) == 0) {
reply_len = wpa_supplicant_ctrl_iface_status(
@@ -8717,6 +9989,22 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
reply_len = wpas_ctrl_iface_pmksa(wpa_s, reply, reply_size);
} else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) {
wpas_ctrl_iface_pmksa_flush(wpa_s);
+#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
+ } else if (os_strncmp(buf, "PMKSA_GET ", 10) == 0) {
+ reply_len = wpas_ctrl_iface_pmksa_get(wpa_s, buf + 10,
+ reply, reply_size);
+ } else if (os_strncmp(buf, "PMKSA_ADD ", 10) == 0) {
+ if (wpas_ctrl_iface_pmksa_add(wpa_s, buf + 10) < 0)
+ reply_len = -1;
+#ifdef CONFIG_MESH
+ } else if (os_strncmp(buf, "MESH_PMKSA_GET ", 15) == 0) {
+ reply_len = wpas_ctrl_iface_mesh_pmksa_get(wpa_s, buf + 15,
+ reply, reply_size);
+ } else if (os_strncmp(buf, "MESH_PMKSA_ADD ", 15) == 0) {
+ if (wpas_ctrl_iface_mesh_pmksa_add(wpa_s, buf + 15) < 0)
+ reply_len = -1;
+#endif /* CONFIG_MESH */
+#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
} else if (os_strncmp(buf, "SET ", 4) == 0) {
if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
reply_len = -1;
@@ -8753,11 +10041,6 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
reply_len = -1;
#endif /* IEEE8021X_EAPOL */
-#ifdef CONFIG_PEERKEY
- } else if (os_strncmp(buf, "STKSTART ", 9) == 0) {
- if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))
- reply_len = -1;
-#endif /* CONFIG_PEERKEY */
#ifdef CONFIG_IEEE80211R
} else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
@@ -9288,6 +10571,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
} else if (os_strncmp(buf, "WNM_BSS_QUERY ", 14) == 0) {
if (wpas_ctrl_iface_wnm_bss_query(wpa_s, buf + 14))
reply_len = -1;
+ } else if (os_strncmp(buf, "COLOC_INTF_REPORT ", 18) == 0) {
+ if (wpas_ctrl_iface_coloc_intf_report(wpa_s, buf + 18))
+ reply_len = -1;
#endif /* CONFIG_WNM */
} else if (os_strcmp(buf, "FLUSH") == 0) {
wpa_supplicant_ctrl_iface_flush(wpa_s);
@@ -9334,6 +10620,21 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
} else if (os_strncmp(buf, "TEST_ASSOC_IE ", 14) == 0) {
if (wpas_ctrl_test_assoc_ie(wpa_s, buf + 14) < 0)
reply_len = -1;
+ } else if (os_strcmp(buf, "RESET_PN") == 0) {
+ if (wpas_ctrl_reset_pn(wpa_s) < 0)
+ reply_len = -1;
+ } else if (os_strncmp(buf, "KEY_REQUEST ", 12) == 0) {
+ if (wpas_ctrl_key_request(wpa_s, buf + 12) < 0)
+ reply_len = -1;
+ } else if (os_strcmp(buf, "RESEND_ASSOC") == 0) {
+ if (wpas_ctrl_resend_assoc(wpa_s) < 0)
+ reply_len = -1;
+#ifdef CONFIG_IEEE80211W
+ } else if (os_strcmp(buf, "UNPROT_DEAUTH") == 0) {
+ sme_event_unprot_disconnect(
+ wpa_s, wpa_s->bssid, NULL,
+ WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
+#endif /* CONFIG_IEEE80211W */
#endif /* CONFIG_TESTING_OPTIONS */
} else if (os_strncmp(buf, "VENDOR_ELEM_ADD ", 16) == 0) {
if (wpas_ctrl_vendor_elem_add(wpa_s, buf + 16) < 0)
@@ -9355,6 +10656,98 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
} else if (os_strncmp(buf, "GET_PREF_FREQ_LIST ", 19) == 0) {
reply_len = wpas_ctrl_iface_get_pref_freq_list(
wpa_s, buf + 19, reply, reply_size);
+#ifdef CONFIG_FILS
+ } else if (os_strncmp(buf, "FILS_HLP_REQ_ADD ", 17) == 0) {
+ if (wpas_ctrl_iface_fils_hlp_req_add(wpa_s, buf + 17))
+ reply_len = -1;
+ } else if (os_strcmp(buf, "FILS_HLP_REQ_FLUSH") == 0) {
+ wpas_flush_fils_hlp_req(wpa_s);
+#endif /* CONFIG_FILS */
+#ifdef CONFIG_DPP
+ } else if (os_strncmp(buf, "DPP_QR_CODE ", 12) == 0) {
+ int res;
+
+ res = wpas_dpp_qr_code(wpa_s, buf + 12);
+ if (res < 0) {
+ reply_len = -1;
+ } else {
+ reply_len = os_snprintf(reply, reply_size, "%d", res);
+ if (os_snprintf_error(reply_size, reply_len))
+ reply_len = -1;
+ }
+ } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) {
+ int res;
+
+ res = dpp_bootstrap_gen(wpa_s->dpp, buf + 18);
+ if (res < 0) {
+ reply_len = -1;
+ } else {
+ reply_len = os_snprintf(reply, reply_size, "%d", res);
+ if (os_snprintf_error(reply_size, reply_len))
+ reply_len = -1;
+ }
+ } else if (os_strncmp(buf, "DPP_BOOTSTRAP_REMOVE ", 21) == 0) {
+ if (dpp_bootstrap_remove(wpa_s->dpp, buf + 21) < 0)
+ reply_len = -1;
+ } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GET_URI ", 22) == 0) {
+ const char *uri;
+
+ uri = dpp_bootstrap_get_uri(wpa_s->dpp, atoi(buf + 22));
+ if (!uri) {
+ reply_len = -1;
+ } else {
+ reply_len = os_snprintf(reply, reply_size, "%s", uri);
+ if (os_snprintf_error(reply_size, reply_len))
+ reply_len = -1;
+ }
+ } else if (os_strncmp(buf, "DPP_BOOTSTRAP_INFO ", 19) == 0) {
+ reply_len = dpp_bootstrap_info(wpa_s->dpp, atoi(buf + 19),
+ reply, reply_size);
+ } else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) {
+ if (wpas_dpp_auth_init(wpa_s, buf + 13) < 0)
+ reply_len = -1;
+ } else if (os_strncmp(buf, "DPP_LISTEN ", 11) == 0) {
+ if (wpas_dpp_listen(wpa_s, buf + 11) < 0)
+ reply_len = -1;
+ } else if (os_strcmp(buf, "DPP_STOP_LISTEN") == 0) {
+ wpas_dpp_stop(wpa_s);
+ wpas_dpp_listen_stop(wpa_s);
+ } else if (os_strncmp(buf, "DPP_CONFIGURATOR_ADD", 20) == 0) {
+ int res;
+
+ res = dpp_configurator_add(wpa_s->dpp, buf + 20);
+ if (res < 0) {
+ reply_len = -1;
+ } else {
+ reply_len = os_snprintf(reply, reply_size, "%d", res);
+ if (os_snprintf_error(reply_size, reply_len))
+ reply_len = -1;
+ }
+ } else if (os_strncmp(buf, "DPP_CONFIGURATOR_REMOVE ", 24) == 0) {
+ if (dpp_configurator_remove(wpa_s->dpp, buf + 24) < 0)
+ reply_len = -1;
+ } else if (os_strncmp(buf, "DPP_CONFIGURATOR_SIGN ", 22) == 0) {
+ if (wpas_dpp_configurator_sign(wpa_s, buf + 21) < 0)
+ reply_len = -1;
+ } else if (os_strncmp(buf, "DPP_CONFIGURATOR_GET_KEY ", 25) == 0) {
+ reply_len = dpp_configurator_get_key_id(wpa_s->dpp,
+ atoi(buf + 25),
+ reply, reply_size);
+ } else if (os_strncmp(buf, "DPP_PKEX_ADD ", 13) == 0) {
+ int res;
+
+ res = wpas_dpp_pkex_add(wpa_s, buf + 12);
+ if (res < 0) {
+ reply_len = -1;
+ } else {
+ reply_len = os_snprintf(reply, reply_size, "%d", res);
+ if (os_snprintf_error(reply_size, reply_len))
+ reply_len = -1;
+ }
+ } else if (os_strncmp(buf, "DPP_PKEX_REMOVE ", 16) == 0) {
+ if (wpas_dpp_pkex_remove(wpa_s, buf + 16) < 0)
+ reply_len = -1;
+#endif /* CONFIG_DPP */
} else {
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
reply_len = 16;
@@ -9664,12 +11057,16 @@ static char * wpas_global_ctrl_iface_redir_p2p(struct wpa_global *global,
"P2P_CANCEL",
"P2P_PRESENCE_REQ",
"P2P_EXT_LISTEN",
+#ifdef CONFIG_AP
+ "STA-FIRST",
+#endif /* CONFIG_AP */
NULL
};
static const char * prefix[] = {
#ifdef ANDROID
"DRIVER ",
#endif /* ANDROID */
+ "GET_CAPABILITY ",
"GET_NETWORK ",
"REMOVE_NETWORK ",
"P2P_FIND ",
@@ -9701,6 +11098,10 @@ static char * wpas_global_ctrl_iface_redir_p2p(struct wpa_global *global,
"NFC_REPORT_HANDOVER ",
"P2P_ASP_PROVISION ",
"P2P_ASP_PROVISION_RESP ",
+#ifdef CONFIG_AP
+ "STA ",
+ "STA-NEXT ",
+#endif /* CONFIG_AP */
NULL
};
int found = 0;
diff --git a/freebsd/contrib/wpa/wpa_supplicant/ctrl_iface_unix.c b/freebsd/contrib/wpa/wpa_supplicant/ctrl_iface_unix.c
index ff1814c9..cab15263 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/ctrl_iface_unix.c
+++ b/freebsd/contrib/wpa/wpa_supplicant/ctrl_iface_unix.c
@@ -105,7 +105,7 @@ static int wpa_supplicant_ctrl_iface_attach(struct dl_list *ctrl_dst,
struct sockaddr_storage *from,
socklen_t fromlen, int global)
{
- return ctrl_iface_attach(ctrl_dst, from, fromlen);
+ return ctrl_iface_attach(ctrl_dst, from, fromlen, NULL);
}
@@ -572,8 +572,8 @@ static int wpas_ctrl_iface_open_sock(struct wpa_supplicant *wpa_s,
}
}
- if (gid_set && chown(dir, -1, gid) < 0) {
- wpa_printf(MSG_ERROR, "chown[ctrl_interface=%s,gid=%d]: %s",
+ if (gid_set && lchown(dir, -1, gid) < 0) {
+ wpa_printf(MSG_ERROR, "lchown[ctrl_interface=%s,gid=%d]: %s",
dir, (int) gid, strerror(errno));
goto fail;
}
@@ -640,8 +640,8 @@ static int wpas_ctrl_iface_open_sock(struct wpa_supplicant *wpa_s,
}
}
- if (gid_set && chown(fname, -1, gid) < 0) {
- wpa_printf(MSG_ERROR, "chown[ctrl_interface=%s,gid=%d]: %s",
+ if (gid_set && lchown(fname, -1, gid) < 0) {
+ wpa_printf(MSG_ERROR, "lchown[ctrl_interface=%s,gid=%d]: %s",
fname, (int) gid, strerror(errno));
goto fail;
}
@@ -1237,9 +1237,9 @@ static int wpas_global_ctrl_iface_open_sock(struct wpa_global *global,
wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d",
(int) gid);
}
- if (chown(ctrl, -1, gid) < 0) {
+ if (lchown(ctrl, -1, gid) < 0) {
wpa_printf(MSG_ERROR,
- "chown[global_ctrl_interface=%s,gid=%d]: %s",
+ "lchown[global_ctrl_interface=%s,gid=%d]: %s",
ctrl, (int) gid, strerror(errno));
goto fail;
}
diff --git a/freebsd/contrib/wpa/wpa_supplicant/dbus/dbus_new.h b/freebsd/contrib/wpa/wpa_supplicant/dbus/dbus_new.h
index d64fceef..42db3892 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/dbus/dbus_new.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/dbus/dbus_new.h
@@ -28,8 +28,14 @@ enum wpas_dbus_prop {
WPAS_DBUS_PROP_CURRENT_NETWORK,
WPAS_DBUS_PROP_CURRENT_AUTH_MODE,
WPAS_DBUS_PROP_BSSS,
+ WPAS_DBUS_PROP_STATIONS,
WPAS_DBUS_PROP_DISCONNECT_REASON,
+ WPAS_DBUS_PROP_AUTH_STATUS_CODE,
WPAS_DBUS_PROP_ASSOC_STATUS_CODE,
+ WPAS_DBUS_PROP_ROAM_TIME,
+ WPAS_DBUS_PROP_ROAM_COMPLETE,
+ WPAS_DBUS_PROP_SESSION_LENGTH,
+ WPAS_DBUS_PROP_BSS_TM_STATUS,
};
enum wpas_dbus_bss_prop {
@@ -45,6 +51,10 @@ enum wpas_dbus_bss_prop {
WPAS_DBUS_BSS_PROP_AGE,
};
+enum wpas_dbus_sta_prop {
+ WPAS_DBUS_STA_PROP_ADDRESS,
+};
+
#define WPAS_DBUS_OBJECT_PATH_MAX 150
#define WPAS_DBUS_NEW_SERVICE "fi.w1.wpa_supplicant1"
@@ -61,9 +71,14 @@ enum wpas_dbus_bss_prop {
#define WPAS_DBUS_NEW_BSSIDS_PART "BSSs"
#define WPAS_DBUS_NEW_IFACE_BSS WPAS_DBUS_NEW_INTERFACE ".BSS"
+#define WPAS_DBUS_NEW_STAS_PART "Stations"
+#define WPAS_DBUS_NEW_IFACE_STA WPAS_DBUS_NEW_INTERFACE ".Station"
+
#define WPAS_DBUS_NEW_IFACE_P2PDEVICE \
WPAS_DBUS_NEW_IFACE_INTERFACE ".P2PDevice"
+#define WPAS_DBUS_NEW_IFACE_MESH WPAS_DBUS_NEW_IFACE_INTERFACE ".Mesh"
+
/*
* Groups correspond to P2P groups where this device is a GO (owner)
*/
@@ -161,6 +176,8 @@ int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
u8 bssid[ETH_ALEN], unsigned int id);
int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
u8 bssid[ETH_ALEN], unsigned int id);
+int wpas_dbus_unregister_sta(struct wpa_supplicant *wpa_s, const u8 *sta);
+int wpas_dbus_register_sta(struct wpa_supplicant *wpa_s, const u8 *sta);
void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s,
const char *name);
void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s,
@@ -190,7 +207,8 @@ void wpas_dbus_signal_p2p_go_neg_req(struct wpa_supplicant *wpa_s,
const u8 *src, u16 dev_passwd_id,
u8 go_intent);
void wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
- int client, int persistent);
+ int client, int persistent,
+ const u8 *ip);
void wpas_dbus_signal_p2p_group_formation_failure(struct wpa_supplicant *wpa_s,
const char *reason);
void wpas_dbus_register_p2p_group(struct wpa_supplicant *wpa_s,
@@ -237,6 +255,15 @@ void wpas_dbus_signal_p2p_invitation_received(struct wpa_supplicant *wpa_s,
const u8 *sa, const u8 *dev_addr,
const u8 *bssid, int id,
int op_freq);
+void wpas_dbus_signal_mesh_group_started(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid);
+void wpas_dbus_signal_mesh_group_removed(struct wpa_supplicant *wpa_s,
+ const u8 *meshid, u8 meshid_len,
+ int reason);
+void wpas_dbus_signal_mesh_peer_connected(struct wpa_supplicant *wpa_s,
+ const u8 *peer_addr);
+void wpas_dbus_signal_mesh_peer_disconnected(struct wpa_supplicant *wpa_s,
+ const u8 *peer_addr, int reason);
#else /* CONFIG_CTRL_IFACE_DBUS_NEW */
@@ -333,6 +360,18 @@ static inline int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
return 0;
}
+static inline int wpas_dbus_unregister_sta(struct wpa_supplicant *wpa_s,
+ const u8 *sta)
+{
+ return 0;
+}
+
+static inline int wpas_dbus_register_sta(struct wpa_supplicant *wpa_s,
+ const u8 *sta)
+{
+ return 0;
+}
+
static inline void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s,
const char *name)
{
@@ -400,7 +439,8 @@ static inline void wpas_dbus_signal_p2p_go_neg_req(struct wpa_supplicant *wpa_s,
static inline void
wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
- int client, int persistent)
+ int client, int persistent,
+ const u8 *ip)
{
}
@@ -551,6 +591,31 @@ void wpas_dbus_signal_p2p_invitation_received(struct wpa_supplicant *wpa_s,
{
}
+static inline
+void wpas_dbus_signal_mesh_group_started(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid)
+{
+}
+
+static inline
+void wpas_dbus_signal_mesh_group_removed(struct wpa_supplicant *wpa_s,
+ const u8 *meshid, u8 meshid_len,
+ int reason)
+{
+}
+
+static inline
+void wpas_dbus_signal_mesh_peer_connected(struct wpa_supplicant *wpa_s,
+ const u8 *peer_addr)
+{
+}
+
+static inline
+void wpas_dbus_signal_mesh_peer_disconnected(struct wpa_supplicant *wpa_s,
+ const u8 *peer_addr, int reason)
+{
+}
+
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
#endif /* CTRL_IFACE_DBUS_H_NEW */
diff --git a/freebsd/contrib/wpa/wpa_supplicant/dbus/dbus_old.h b/freebsd/contrib/wpa/wpa_supplicant/dbus/dbus_old.h
deleted file mode 100644
index 451a9f82..00000000
--- a/freebsd/contrib/wpa/wpa_supplicant/dbus/dbus_old.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * WPA Supplicant / dbus-based control interface
- * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#ifndef CTRL_IFACE_DBUS_H
-#define CTRL_IFACE_DBUS_H
-
-struct wps_credential;
-
-#ifdef CONFIG_CTRL_IFACE_DBUS
-
-#define WPAS_DBUS_OBJECT_PATH_MAX 150
-
-#define WPAS_DBUS_SERVICE "fi.epitest.hostap.WPASupplicant"
-#define WPAS_DBUS_PATH "/fi/epitest/hostap/WPASupplicant"
-#define WPAS_DBUS_INTERFACE "fi.epitest.hostap.WPASupplicant"
-
-#define WPAS_DBUS_PATH_INTERFACES WPAS_DBUS_PATH "/Interfaces"
-#define WPAS_DBUS_IFACE_INTERFACE WPAS_DBUS_INTERFACE ".Interface"
-
-#define WPAS_DBUS_NETWORKS_PART "Networks"
-#define WPAS_DBUS_IFACE_NETWORK WPAS_DBUS_INTERFACE ".Network"
-
-#define WPAS_DBUS_BSSIDS_PART "BSSIDs"
-#define WPAS_DBUS_IFACE_BSSID WPAS_DBUS_INTERFACE ".BSSID"
-
-
-/* Errors */
-#define WPAS_ERROR_INVALID_NETWORK \
- WPAS_DBUS_IFACE_INTERFACE ".InvalidNetwork"
-#define WPAS_ERROR_INVALID_BSSID \
- WPAS_DBUS_IFACE_INTERFACE ".InvalidBSSID"
-
-#define WPAS_ERROR_INVALID_OPTS \
- WPAS_DBUS_INTERFACE ".InvalidOptions"
-#define WPAS_ERROR_INVALID_IFACE \
- WPAS_DBUS_INTERFACE ".InvalidInterface"
-
-#define WPAS_ERROR_ADD_ERROR \
- WPAS_DBUS_INTERFACE ".AddError"
-#define WPAS_ERROR_EXISTS_ERROR \
- WPAS_DBUS_INTERFACE ".ExistsError"
-#define WPAS_ERROR_REMOVE_ERROR \
- WPAS_DBUS_INTERFACE ".RemoveError"
-
-#define WPAS_ERROR_SCAN_ERROR \
- WPAS_DBUS_IFACE_INTERFACE ".ScanError"
-#define WPAS_ERROR_ADD_NETWORK_ERROR \
- WPAS_DBUS_IFACE_INTERFACE ".AddNetworkError"
-#define WPAS_ERROR_INTERNAL_ERROR \
- WPAS_DBUS_IFACE_INTERFACE ".InternalError"
-#define WPAS_ERROR_REMOVE_NETWORK_ERROR \
- WPAS_DBUS_IFACE_INTERFACE ".RemoveNetworkError"
-
-#define WPAS_ERROR_WPS_PBC_ERROR \
- WPAS_DBUS_IFACE_INTERFACE ".WpsPbcError"
-#define WPAS_ERROR_WPS_PIN_ERROR \
- WPAS_DBUS_IFACE_INTERFACE ".WpsPinError"
-#define WPAS_ERROR_WPS_REG_ERROR \
- WPAS_DBUS_IFACE_INTERFACE ".WpsRegError"
-
-#define WPAS_DBUS_BSSID_FORMAT "%02x%02x%02x%02x%02x%02x"
-
-struct wpa_global;
-struct wpa_supplicant;
-
-int wpa_supplicant_dbus_ctrl_iface_init(struct wpas_dbus_priv *iface);
-void wpa_supplicant_dbus_notify_scan_results(struct wpa_supplicant *wpa_s);
-void wpa_supplicant_dbus_notify_scanning(struct wpa_supplicant *wpa_s);
-void wpa_supplicant_dbus_notify_state_change(struct wpa_supplicant *wpa_s,
- enum wpa_states new_state,
- enum wpa_states old_state);
-void wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s,
- const struct wps_credential *cred);
-void wpa_supplicant_dbus_notify_certification(struct wpa_supplicant *wpa_s,
- int depth, const char *subject,
- const char *cert_hash,
- const struct wpabuf *cert);
-
-char * wpas_dbus_decompose_object_path(const char *path, char **network,
- char **bssid);
-
-int wpas_dbus_register_iface(struct wpa_supplicant *wpa_s);
-int wpas_dbus_unregister_iface(struct wpa_supplicant *wpa_s);
-
-
-/* Methods internal to the dbus control interface */
-struct wpa_supplicant * wpa_supplicant_get_iface_by_dbus_path(
- struct wpa_global *global, const char *path);
-
-#else /* CONFIG_CTRL_IFACE_DBUS */
-
-static inline void
-wpa_supplicant_dbus_notify_scan_results(struct wpa_supplicant *wpa_s)
-{
-}
-
-static inline void
-wpa_supplicant_dbus_notify_scanning(struct wpa_supplicant *wpa_s)
-{
-}
-
-static inline void
-wpa_supplicant_dbus_notify_state_change(struct wpa_supplicant *wpa_s,
- enum wpa_states new_state,
- enum wpa_states old_state)
-{
-}
-
-static inline void
-wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s,
- const struct wps_credential *cred)
-{
-}
-
-static inline void
-wpa_supplicant_dbus_notify_certification(struct wpa_supplicant *wpa_s,
- int depth, const char *subject,
- const char *cert_hash,
- const struct wpabuf *cert)
-{
-}
-
-static inline int
-wpas_dbus_register_iface(struct wpa_supplicant *wpa_s)
-{
- return 0;
-}
-
-static inline int
-wpas_dbus_unregister_iface(struct wpa_supplicant *wpa_s)
-{
- return 0;
-}
-
-#endif /* CONFIG_CTRL_IFACE_DBUS */
-
-#endif /* CTRL_IFACE_DBUS_H */
diff --git a/freebsd/contrib/wpa/wpa_supplicant/dpp_supplicant.h b/freebsd/contrib/wpa/wpa_supplicant/dpp_supplicant.h
new file mode 100644
index 00000000..ecb7a7d6
--- /dev/null
+++ b/freebsd/contrib/wpa/wpa_supplicant/dpp_supplicant.h
@@ -0,0 +1,29 @@
+/*
+ * wpa_supplicant - DPP
+ * Copyright (c) 2017, Qualcomm Atheros, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef DPP_SUPPLICANT_H
+#define DPP_SUPPLICANT_H
+
+int wpas_dpp_qr_code(struct wpa_supplicant *wpa_s, const char *cmd);
+int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd);
+int wpas_dpp_listen(struct wpa_supplicant *wpa_s, const char *cmd);
+void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s);
+void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
+ unsigned int freq);
+void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
+ const u8 *buf, size_t len, unsigned int freq);
+int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd);
+int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd);
+int wpas_dpp_pkex_remove(struct wpa_supplicant *wpa_s, const char *id);
+void wpas_dpp_stop(struct wpa_supplicant *wpa_s);
+int wpas_dpp_init(struct wpa_supplicant *wpa_s);
+void wpas_dpp_deinit(struct wpa_supplicant *wpa_s);
+int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
+ struct wpa_bss *bss);
+
+#endif /* DPP_SUPPLICANT_H */
diff --git a/freebsd/contrib/wpa/wpa_supplicant/driver_i.h b/freebsd/contrib/wpa/wpa_supplicant/driver_i.h
index 220b7ba3..4a9f472e 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/driver_i.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/driver_i.h
@@ -189,20 +189,19 @@ static inline int wpa_drv_deauthenticate(struct wpa_supplicant *wpa_s,
}
static inline int wpa_drv_add_pmkid(struct wpa_supplicant *wpa_s,
- const u8 *bssid, const u8 *pmkid)
+ struct wpa_pmkid_params *params)
{
if (wpa_s->driver->add_pmkid) {
- return wpa_s->driver->add_pmkid(wpa_s->drv_priv, bssid, pmkid);
+ return wpa_s->driver->add_pmkid(wpa_s->drv_priv, params);
}
return -1;
}
static inline int wpa_drv_remove_pmkid(struct wpa_supplicant *wpa_s,
- const u8 *bssid, const u8 *pmkid)
+ struct wpa_pmkid_params *params)
{
if (wpa_s->driver->remove_pmkid) {
- return wpa_s->driver->remove_pmkid(wpa_s->drv_priv, bssid,
- pmkid);
+ return wpa_s->driver->remove_pmkid(wpa_s->drv_priv, params);
}
return -1;
}
@@ -276,11 +275,12 @@ static inline int wpa_drv_mlme_setprotection(struct wpa_supplicant *wpa_s,
static inline struct hostapd_hw_modes *
wpa_drv_get_hw_feature_data(struct wpa_supplicant *wpa_s, u16 *num_modes,
- u16 *flags)
+ u16 *flags, u8 *dfs_domain)
{
if (wpa_s->driver->get_hw_feature_data)
return wpa_s->driver->get_hw_feature_data(wpa_s->drv_priv,
- num_modes, flags);
+ num_modes, flags,
+ dfs_domain);
return NULL;
}
@@ -492,6 +492,14 @@ static inline int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
return -1;
}
+static inline int wpa_drv_channel_info(struct wpa_supplicant *wpa_s,
+ struct wpa_channel_info *ci)
+{
+ if (wpa_s->driver->channel_info)
+ return wpa_s->driver->channel_info(wpa_s->drv_priv, ci);
+ return -1;
+}
+
static inline int wpa_drv_pktcnt_poll(struct wpa_supplicant *wpa_s,
struct hostap_sta_driver_data *sta)
{
@@ -689,6 +697,14 @@ static inline int wpa_drv_roaming(struct wpa_supplicant *wpa_s, int allowed,
return wpa_s->driver->roaming(wpa_s->drv_priv, allowed, bssid);
}
+static inline int wpa_drv_disable_fils(struct wpa_supplicant *wpa_s,
+ int disable)
+{
+ if (!wpa_s->driver->disable_fils)
+ return -1;
+ return wpa_s->driver->disable_fils(wpa_s->drv_priv, disable);
+}
+
static inline int wpa_drv_set_mac_addr(struct wpa_supplicant *wpa_s,
const u8 *addr)
{
@@ -715,6 +731,14 @@ static inline int wpa_drv_macsec_deinit(struct wpa_supplicant *wpa_s)
return wpa_s->driver->macsec_deinit(wpa_s->drv_priv);
}
+static inline int wpa_drv_macsec_get_capability(struct wpa_supplicant *wpa_s,
+ enum macsec_cap *cap)
+{
+ if (!wpa_s->driver->macsec_get_capability)
+ return -1;
+ return wpa_s->driver->macsec_get_capability(wpa_s->drv_priv, cap);
+}
+
static inline int wpa_drv_enable_protect_frames(struct wpa_supplicant *wpa_s,
Boolean enabled)
{
@@ -723,6 +747,14 @@ static inline int wpa_drv_enable_protect_frames(struct wpa_supplicant *wpa_s,
return wpa_s->driver->enable_protect_frames(wpa_s->drv_priv, enabled);
}
+static inline int wpa_drv_enable_encrypt(struct wpa_supplicant *wpa_s,
+ Boolean enabled)
+{
+ if (!wpa_s->driver->enable_encrypt)
+ return -1;
+ return wpa_s->driver->enable_encrypt(wpa_s->drv_priv, enabled);
+}
+
static inline int wpa_drv_set_replay_protect(struct wpa_supplicant *wpa_s,
Boolean enabled, u32 window)
{
@@ -749,145 +781,135 @@ static inline int wpa_drv_enable_controlled_port(struct wpa_supplicant *wpa_s,
}
static inline int wpa_drv_get_receive_lowest_pn(struct wpa_supplicant *wpa_s,
- u32 channel, u8 an,
- u32 *lowest_pn)
+ struct receive_sa *sa)
{
if (!wpa_s->driver->get_receive_lowest_pn)
return -1;
- return wpa_s->driver->get_receive_lowest_pn(wpa_s->drv_priv, channel,
- an, lowest_pn);
+ return wpa_s->driver->get_receive_lowest_pn(wpa_s->drv_priv, sa);
}
static inline int wpa_drv_get_transmit_next_pn(struct wpa_supplicant *wpa_s,
- u32 channel, u8 an,
- u32 *next_pn)
+ struct transmit_sa *sa)
{
if (!wpa_s->driver->get_transmit_next_pn)
return -1;
- return wpa_s->driver->get_transmit_next_pn(wpa_s->drv_priv, channel,
- an, next_pn);
+ return wpa_s->driver->get_transmit_next_pn(wpa_s->drv_priv, sa);
}
static inline int wpa_drv_set_transmit_next_pn(struct wpa_supplicant *wpa_s,
- u32 channel, u8 an,
- u32 next_pn)
+ struct transmit_sa *sa)
{
if (!wpa_s->driver->set_transmit_next_pn)
return -1;
- return wpa_s->driver->set_transmit_next_pn(wpa_s->drv_priv, channel,
- an, next_pn);
+ return wpa_s->driver->set_transmit_next_pn(wpa_s->drv_priv, sa);
}
-static inline int wpa_drv_get_available_receive_sc(struct wpa_supplicant *wpa_s,
- u32 *channel)
+static inline int wpa_drv_set_receive_lowest_pn(struct wpa_supplicant *wpa_s,
+ struct receive_sa *sa)
{
- if (!wpa_s->driver->get_available_receive_sc)
+ if (!wpa_s->driver->set_receive_lowest_pn)
return -1;
- return wpa_s->driver->get_available_receive_sc(wpa_s->drv_priv,
- channel);
+ return wpa_s->driver->set_receive_lowest_pn(wpa_s->drv_priv, sa);
}
static inline int
-wpa_drv_create_receive_sc(struct wpa_supplicant *wpa_s, u32 channel,
- const u8 *sci_addr, u16 sci_port,
+wpa_drv_create_receive_sc(struct wpa_supplicant *wpa_s, struct receive_sc *sc,
unsigned int conf_offset, int validation)
{
if (!wpa_s->driver->create_receive_sc)
return -1;
- return wpa_s->driver->create_receive_sc(wpa_s->drv_priv, channel,
- sci_addr, sci_port, conf_offset,
- validation);
+ return wpa_s->driver->create_receive_sc(wpa_s->drv_priv, sc,
+ conf_offset, validation);
}
static inline int wpa_drv_delete_receive_sc(struct wpa_supplicant *wpa_s,
- u32 channel)
+ struct receive_sc *sc)
{
if (!wpa_s->driver->delete_receive_sc)
return -1;
- return wpa_s->driver->delete_receive_sc(wpa_s->drv_priv, channel);
+ return wpa_s->driver->delete_receive_sc(wpa_s->drv_priv, sc);
}
static inline int wpa_drv_create_receive_sa(struct wpa_supplicant *wpa_s,
- u32 channel, u8 an,
- u32 lowest_pn, const u8 *sak)
+ struct receive_sa *sa)
{
if (!wpa_s->driver->create_receive_sa)
return -1;
- return wpa_s->driver->create_receive_sa(wpa_s->drv_priv, channel, an,
- lowest_pn, sak);
+ return wpa_s->driver->create_receive_sa(wpa_s->drv_priv, sa);
}
-static inline int wpa_drv_enable_receive_sa(struct wpa_supplicant *wpa_s,
- u32 channel, u8 an)
+static inline int wpa_drv_delete_receive_sa(struct wpa_supplicant *wpa_s,
+ struct receive_sa *sa)
{
- if (!wpa_s->driver->enable_receive_sa)
+ if (!wpa_s->driver->delete_receive_sa)
return -1;
- return wpa_s->driver->enable_receive_sa(wpa_s->drv_priv, channel, an);
+ return wpa_s->driver->delete_receive_sa(wpa_s->drv_priv, sa);
}
-static inline int wpa_drv_disable_receive_sa(struct wpa_supplicant *wpa_s,
- u32 channel, u8 an)
+static inline int wpa_drv_enable_receive_sa(struct wpa_supplicant *wpa_s,
+ struct receive_sa *sa)
{
- if (!wpa_s->driver->disable_receive_sa)
+ if (!wpa_s->driver->enable_receive_sa)
return -1;
- return wpa_s->driver->disable_receive_sa(wpa_s->drv_priv, channel, an);
+ return wpa_s->driver->enable_receive_sa(wpa_s->drv_priv, sa);
}
-static inline int
-wpa_drv_get_available_transmit_sc(struct wpa_supplicant *wpa_s, u32 *channel)
+static inline int wpa_drv_disable_receive_sa(struct wpa_supplicant *wpa_s,
+ struct receive_sa *sa)
{
- if (!wpa_s->driver->get_available_transmit_sc)
+ if (!wpa_s->driver->disable_receive_sa)
return -1;
- return wpa_s->driver->get_available_transmit_sc(wpa_s->drv_priv,
- channel);
+ return wpa_s->driver->disable_receive_sa(wpa_s->drv_priv, sa);
}
static inline int
-wpa_drv_create_transmit_sc(struct wpa_supplicant *wpa_s, u32 channel,
- const u8 *sci_addr, u16 sci_port,
+wpa_drv_create_transmit_sc(struct wpa_supplicant *wpa_s, struct transmit_sc *sc,
unsigned int conf_offset)
{
if (!wpa_s->driver->create_transmit_sc)
return -1;
- return wpa_s->driver->create_transmit_sc(wpa_s->drv_priv, channel,
- sci_addr, sci_port,
+ return wpa_s->driver->create_transmit_sc(wpa_s->drv_priv, sc,
conf_offset);
}
static inline int wpa_drv_delete_transmit_sc(struct wpa_supplicant *wpa_s,
- u32 channel)
+ struct transmit_sc *sc)
{
if (!wpa_s->driver->delete_transmit_sc)
return -1;
- return wpa_s->driver->delete_transmit_sc(wpa_s->drv_priv, channel);
+ return wpa_s->driver->delete_transmit_sc(wpa_s->drv_priv, sc);
}
static inline int wpa_drv_create_transmit_sa(struct wpa_supplicant *wpa_s,
- u32 channel, u8 an,
- u32 next_pn,
- Boolean confidentiality,
- const u8 *sak)
+ struct transmit_sa *sa)
{
if (!wpa_s->driver->create_transmit_sa)
return -1;
- return wpa_s->driver->create_transmit_sa(wpa_s->drv_priv, channel, an,
- next_pn, confidentiality, sak);
+ return wpa_s->driver->create_transmit_sa(wpa_s->drv_priv, sa);
+}
+
+static inline int wpa_drv_delete_transmit_sa(struct wpa_supplicant *wpa_s,
+ struct transmit_sa *sa)
+{
+ if (!wpa_s->driver->delete_transmit_sa)
+ return -1;
+ return wpa_s->driver->delete_transmit_sa(wpa_s->drv_priv, sa);
}
static inline int wpa_drv_enable_transmit_sa(struct wpa_supplicant *wpa_s,
- u32 channel, u8 an)
+ struct transmit_sa *sa)
{
if (!wpa_s->driver->enable_transmit_sa)
return -1;
- return wpa_s->driver->enable_transmit_sa(wpa_s->drv_priv, channel, an);
+ return wpa_s->driver->enable_transmit_sa(wpa_s->drv_priv, sa);
}
static inline int wpa_drv_disable_transmit_sa(struct wpa_supplicant *wpa_s,
- u32 channel, u8 an)
+ struct transmit_sa *sa)
{
if (!wpa_s->driver->disable_transmit_sa)
return -1;
- return wpa_s->driver->disable_transmit_sa(wpa_s->drv_priv, channel, an);
+ return wpa_s->driver->disable_transmit_sa(wpa_s->drv_priv, sa);
}
#endif /* CONFIG_MACSEC */
@@ -904,6 +926,11 @@ static inline int wpa_drv_get_pref_freq_list(struct wpa_supplicant *wpa_s,
unsigned int *num,
unsigned int *freq_list)
{
+#ifdef CONFIG_TESTING_OPTIONS
+ if (wpa_s->get_pref_freq_list_override)
+ return wpas_ctrl_iface_get_pref_freq_list_override(
+ wpa_s, if_type, num, freq_list);
+#endif /* CONFIG_TESTING_OPTIONS */
if (!wpa_s->driver->get_pref_freq_list)
return -1;
return wpa_s->driver->get_pref_freq_list(wpa_s->drv_priv, if_type,
@@ -918,11 +945,12 @@ static inline int wpa_drv_set_prob_oper_freq(struct wpa_supplicant *wpa_s,
return wpa_s->driver->set_prob_oper_freq(wpa_s->drv_priv, freq);
}
-static inline int wpa_drv_abort_scan(struct wpa_supplicant *wpa_s)
+static inline int wpa_drv_abort_scan(struct wpa_supplicant *wpa_s,
+ u64 scan_cookie)
{
if (!wpa_s->driver->abort_scan)
return -1;
- return wpa_s->driver->abort_scan(wpa_s->drv_priv);
+ return wpa_s->driver->abort_scan(wpa_s->drv_priv, scan_cookie);
}
static inline int wpa_drv_configure_frame_filters(struct wpa_supplicant *wpa_s,
@@ -976,4 +1004,70 @@ static inline int wpa_drv_set_default_scan_ies(struct wpa_supplicant *wpa_s,
return wpa_s->driver->set_default_scan_ies(wpa_s->drv_priv, ies, len);
}
+static inline int wpa_drv_set_tdls_mode(struct wpa_supplicant *wpa_s,
+ int tdls_external_control)
+{
+ if (!wpa_s->driver->set_tdls_mode)
+ return -1;
+ return wpa_s->driver->set_tdls_mode(wpa_s->drv_priv,
+ tdls_external_control);
+}
+
+static inline struct wpa_bss_candidate_info *
+wpa_drv_get_bss_trans_status(struct wpa_supplicant *wpa_s,
+ struct wpa_bss_trans_info *params)
+{
+ if (!wpa_s->driver->get_bss_transition_status)
+ return NULL;
+ return wpa_s->driver->get_bss_transition_status(wpa_s->drv_priv,
+ params);
+}
+
+static inline int wpa_drv_ignore_assoc_disallow(struct wpa_supplicant *wpa_s,
+ int val)
+{
+ if (!wpa_s->driver->ignore_assoc_disallow)
+ return -1;
+ return wpa_s->driver->ignore_assoc_disallow(wpa_s->drv_priv, val);
+}
+
+static inline int wpa_drv_set_bssid_blacklist(struct wpa_supplicant *wpa_s,
+ unsigned int num_bssid,
+ const u8 *bssids)
+{
+ if (!wpa_s->driver->set_bssid_blacklist)
+ return -1;
+ return wpa_s->driver->set_bssid_blacklist(wpa_s->drv_priv, num_bssid,
+ bssids);
+}
+
+static inline int wpa_drv_update_connect_params(
+ struct wpa_supplicant *wpa_s,
+ struct wpa_driver_associate_params *params,
+ enum wpa_drv_update_connect_params_mask mask)
+{
+ if (!wpa_s->driver->update_connect_params)
+ return -1;
+ return wpa_s->driver->update_connect_params(wpa_s->drv_priv, params,
+ mask);
+}
+
+static inline int
+wpa_drv_send_external_auth_status(struct wpa_supplicant *wpa_s,
+ struct external_auth *params)
+{
+ if (!wpa_s->driver->send_external_auth_status)
+ return -1;
+ return wpa_s->driver->send_external_auth_status(wpa_s->drv_priv,
+ params);
+}
+
+static inline int wpa_drv_set_4addr_mode(struct wpa_supplicant *wpa_s, int val)
+{
+ if (!wpa_s->driver->set_4addr_mode)
+ return -1;
+ return wpa_s->driver->set_4addr_mode(wpa_s->drv_priv,
+ wpa_s->bridge_ifname, val);
+}
+
#endif /* DRIVER_I_H */
diff --git a/freebsd/contrib/wpa/wpa_supplicant/events.c b/freebsd/contrib/wpa/wpa_supplicant/events.c
index 1ed27b58..8673d09c 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/events.c
+++ b/freebsd/contrib/wpa/wpa_supplicant/events.c
@@ -2,7 +2,7 @@
/*
* WPA Supplicant - Driver event processing
- * Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -30,6 +30,8 @@
#include "notify.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
+#include "common/gas_server.h"
+#include "common/dpp.h"
#include "crypto/random.h"
#include "blacklist.h"
#include "wpas_glue.h"
@@ -48,6 +50,10 @@
#include "mesh.h"
#include "mesh_mpm.h"
#include "wmm_ac.h"
+#include "dpp_supplicant.h"
+
+
+#define MAX_OWE_TRANSITION_BSS_SELECT_COUNT 5
#ifndef CONFIG_NO_SCAN_PROCESSING
@@ -56,8 +62,7 @@ static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_NO_SCAN_PROCESSING */
-static int wpas_temp_disabled(struct wpa_supplicant *wpa_s,
- struct wpa_ssid *ssid)
+int wpas_temp_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
{
struct os_reltime now;
@@ -291,6 +296,13 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s)
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
return;
+ if (os_reltime_initialized(&wpa_s->session_start)) {
+ os_reltime_age(&wpa_s->session_start, &wpa_s->session_length);
+ wpa_s->session_start.sec = 0;
+ wpa_s->session_start.usec = 0;
+ wpas_notify_session_length(wpa_s);
+ }
+
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
os_memset(wpa_s->bssid, 0, ETH_ALEN);
@@ -304,7 +316,9 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s)
eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
- if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt))
+ if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
+ wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
+ wpa_s->key_mgmt == WPA_KEY_MGMT_DPP)
eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
wpa_s->ap_ies_from_associnfo = 0;
wpa_s->current_ssid = NULL;
@@ -313,6 +327,16 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s)
wpas_rrm_reset(wpa_s);
wpa_s->wnmsleep_used = 0;
+ wnm_clear_coloc_intf_reporting(wpa_s);
+
+#ifdef CONFIG_TESTING_OPTIONS
+ wpa_s->last_tk_alg = WPA_ALG_NONE;
+ os_memset(wpa_s->last_tk, 0, sizeof(wpa_s->last_tk));
+#endif /* CONFIG_TESTING_OPTIONS */
+ wpa_s->ieee80211ac = 0;
+
+ if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
+ wpa_s->enabled_4addr_mode = 0;
}
@@ -329,7 +353,7 @@ static void wpa_find_assoc_pmkid(struct wpa_supplicant *wpa_s)
for (i = 0; i < ie.num_pmkid; i++) {
pmksa_set = pmksa_cache_set_current(wpa_s->wpa,
ie.pmkid + i * PMKID_LEN,
- NULL, NULL, 0);
+ NULL, NULL, 0, NULL, 0);
if (pmksa_set == 0) {
eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
break;
@@ -481,6 +505,11 @@ static int wpa_supplicant_match_privacy(struct wpa_bss *bss,
return 1;
#endif /* CONFIG_WPS */
+#ifdef CONFIG_OWE
+ if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) && !ssid->owe_only)
+ return 1;
+#endif /* CONFIG_OWE */
+
if (has_wep_key(ssid))
privacy = 1;
@@ -505,7 +534,7 @@ static int wpa_supplicant_match_privacy(struct wpa_bss *bss,
static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid,
- struct wpa_bss *bss)
+ struct wpa_bss *bss, int debug_print)
{
struct wpa_ie_data ie;
int proto_match = 0;
@@ -524,44 +553,63 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
(ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA));
rsn_ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
- while ((ssid->proto & WPA_PROTO_RSN) && rsn_ie) {
+ while ((ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)) && rsn_ie) {
proto_match++;
if (wpa_parse_wpa_ie(rsn_ie, 2 + rsn_ie[1], &ie)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip RSN IE - parse "
- "failed");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip RSN IE - parse failed");
break;
}
+ if (!ie.has_pairwise)
+ ie.pairwise_cipher = wpa_default_rsn_cipher(bss->freq);
+ if (!ie.has_group)
+ ie.group_cipher = wpa_default_rsn_cipher(bss->freq);
if (wep_ok &&
(ie.group_cipher & (WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)))
{
- wpa_dbg(wpa_s, MSG_DEBUG, " selected based on TSN "
- "in RSN IE");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " selected based on TSN in RSN IE");
return 1;
}
- if (!(ie.proto & ssid->proto)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip RSN IE - proto "
- "mismatch");
+ if (!(ie.proto & ssid->proto) &&
+ !(ssid->proto & WPA_PROTO_OSEN)) {
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip RSN IE - proto mismatch");
break;
}
if (!(ie.pairwise_cipher & ssid->pairwise_cipher)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip RSN IE - PTK "
- "cipher mismatch");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip RSN IE - PTK cipher mismatch");
break;
}
if (!(ie.group_cipher & ssid->group_cipher)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip RSN IE - GTK "
- "cipher mismatch");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip RSN IE - GTK cipher mismatch");
+ break;
+ }
+
+ if (ssid->group_mgmt_cipher &&
+ !(ie.mgmt_group_cipher & ssid->group_mgmt_cipher)) {
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip RSN IE - group mgmt cipher mismatch");
break;
}
if (!(ie.key_mgmt & ssid->key_mgmt)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip RSN IE - key mgmt "
- "mismatch");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip RSN IE - key mgmt mismatch");
break;
}
@@ -569,16 +617,18 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
if (!(ie.capabilities & WPA_CAPABILITY_MFPC) &&
wpas_get_ssid_pmf(wpa_s, ssid) ==
MGMT_FRAME_PROTECTION_REQUIRED) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip RSN IE - no mgmt "
- "frame protection");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip RSN IE - no mgmt frame protection");
break;
}
#endif /* CONFIG_IEEE80211W */
if ((ie.capabilities & WPA_CAPABILITY_MFPR) &&
wpas_get_ssid_pmf(wpa_s, ssid) ==
NO_MGMT_FRAME_PROTECTION) {
- wpa_dbg(wpa_s, MSG_DEBUG,
- " skip RSN IE - no mgmt frame protection enabled but AP requires it");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip RSN IE - no mgmt frame protection enabled but AP requires it");
break;
}
#ifdef CONFIG_MBO
@@ -586,20 +636,25 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
wpas_mbo_get_bss_attr(bss, MBO_ATTR_ID_AP_CAPA_IND) &&
wpas_get_ssid_pmf(wpa_s, ssid) !=
NO_MGMT_FRAME_PROTECTION) {
- wpa_dbg(wpa_s, MSG_DEBUG,
- " skip RSN IE - no mgmt frame protection enabled on MBO AP");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip RSN IE - no mgmt frame protection enabled on MBO AP");
break;
}
#endif /* CONFIG_MBO */
- wpa_dbg(wpa_s, MSG_DEBUG, " selected based on RSN IE");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " selected based on RSN IE");
return 1;
}
#ifdef CONFIG_IEEE80211W
- if (wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
- wpa_dbg(wpa_s, MSG_DEBUG,
- " skip - MFP Required but network not MFP Capable");
+ if (wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED &&
+ (!(ssid->key_mgmt & WPA_KEY_MGMT_OWE) || ssid->owe_only)) {
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - MFP Required but network not MFP Capable");
return 0;
}
#endif /* CONFIG_IEEE80211W */
@@ -609,72 +664,110 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
proto_match++;
if (wpa_parse_wpa_ie(wpa_ie, 2 + wpa_ie[1], &ie)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip WPA IE - parse "
- "failed");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip WPA IE - parse failed");
break;
}
if (wep_ok &&
(ie.group_cipher & (WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)))
{
- wpa_dbg(wpa_s, MSG_DEBUG, " selected based on TSN "
- "in WPA IE");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " selected based on TSN in WPA IE");
return 1;
}
if (!(ie.proto & ssid->proto)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip WPA IE - proto "
- "mismatch");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip WPA IE - proto mismatch");
break;
}
if (!(ie.pairwise_cipher & ssid->pairwise_cipher)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip WPA IE - PTK "
- "cipher mismatch");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip WPA IE - PTK cipher mismatch");
break;
}
if (!(ie.group_cipher & ssid->group_cipher)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip WPA IE - GTK "
- "cipher mismatch");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip WPA IE - GTK cipher mismatch");
break;
}
if (!(ie.key_mgmt & ssid->key_mgmt)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip WPA IE - key mgmt "
- "mismatch");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip WPA IE - key mgmt mismatch");
break;
}
- wpa_dbg(wpa_s, MSG_DEBUG, " selected based on WPA IE");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " selected based on WPA IE");
return 1;
}
if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && !wpa_ie &&
!rsn_ie) {
- wpa_dbg(wpa_s, MSG_DEBUG, " allow for non-WPA IEEE 802.1X");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " allow for non-WPA IEEE 802.1X");
return 1;
}
+#ifdef CONFIG_OWE
+ if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) && !ssid->owe_only &&
+ !wpa_ie && !rsn_ie) {
+ if (wpa_s->owe_transition_select &&
+ wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE) &&
+ ssid->owe_transition_bss_select_count + 1 <=
+ MAX_OWE_TRANSITION_BSS_SELECT_COUNT) {
+ ssid->owe_transition_bss_select_count++;
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip OWE transition BSS (selection count %d does not exceed %d)",
+ ssid->owe_transition_bss_select_count,
+ MAX_OWE_TRANSITION_BSS_SELECT_COUNT);
+ wpa_s->owe_transition_search = 1;
+ return 0;
+ }
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " allow in OWE transition mode");
+ return 1;
+ }
+#endif /* CONFIG_OWE */
+
if ((ssid->proto & (WPA_PROTO_WPA | WPA_PROTO_RSN)) &&
wpa_key_mgmt_wpa(ssid->key_mgmt) && proto_match == 0) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - no WPA/RSN proto match");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - no WPA/RSN proto match");
return 0;
}
if ((ssid->key_mgmt & WPA_KEY_MGMT_OSEN) &&
wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " allow in OSEN");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG, " allow in OSEN");
return 1;
}
if (!wpa_key_mgmt_wpa(ssid->key_mgmt)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " allow in non-WPA/WPA2");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG, " allow in non-WPA/WPA2");
return 1;
}
- wpa_dbg(wpa_s, MSG_DEBUG, " reject due to mismatch with "
- "WPA/WPA2");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " reject due to mismatch with WPA/WPA2");
return 0;
}
@@ -694,7 +787,8 @@ static int freq_allowed(int *freqs, int freq)
}
-static int rate_match(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
+static int rate_match(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
+ int debug_print)
{
const struct hostapd_hw_modes *mode = NULL, *modes;
const u8 scan_ie[2] = { WLAN_EID_SUPP_RATES, WLAN_EID_EXT_SUPP_RATES };
@@ -751,9 +845,9 @@ static int rate_match(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
if (flagged && ((rate_ie[j] & 0x7f) ==
BSS_MEMBERSHIP_SELECTOR_HT_PHY)) {
if (!ht_supported(mode)) {
- wpa_dbg(wpa_s, MSG_DEBUG,
- " hardware does not support "
- "HT PHY");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " hardware does not support HT PHY");
return 0;
}
continue;
@@ -763,9 +857,9 @@ static int rate_match(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
if (flagged && ((rate_ie[j] & 0x7f) ==
BSS_MEMBERSHIP_SELECTOR_VHT_PHY)) {
if (!vht_supported(mode)) {
- wpa_dbg(wpa_s, MSG_DEBUG,
- " hardware does not support "
- "VHT PHY");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " hardware does not support VHT PHY");
return 0;
}
continue;
@@ -785,10 +879,11 @@ static int rate_match(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
* order to join a BSS all required rates
* have to be supported by the hardware.
*/
- wpa_dbg(wpa_s, MSG_DEBUG,
- " hardware does not support required rate %d.%d Mbps (freq=%d mode==%d num_rates=%d)",
- r / 10, r % 10,
- bss->freq, mode->mode, mode->num_rates);
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " hardware does not support required rate %d.%d Mbps (freq=%d mode==%d num_rates=%d)",
+ r / 10, r % 10,
+ bss->freq, mode->mode, mode->num_rates);
return 0;
}
}
@@ -841,39 +936,124 @@ static int addr_in_list(const u8 *addr, const u8 *list, size_t num)
}
+static void owe_trans_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
+ const u8 **ret_ssid, size_t *ret_ssid_len)
+{
+#ifdef CONFIG_OWE
+ const u8 *owe, *pos, *end, *bssid;
+ u8 ssid_len;
+ struct wpa_bss *open_bss;
+
+ owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
+ if (!owe || !wpa_bss_get_ie(bss, WLAN_EID_RSN))
+ return;
+
+ pos = owe + 6;
+ end = owe + 2 + owe[1];
+
+ if (end - pos < ETH_ALEN + 1)
+ return;
+ bssid = pos;
+ pos += ETH_ALEN;
+ ssid_len = *pos++;
+ if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
+ return;
+
+ /* Match the profile SSID against the OWE transition mode SSID on the
+ * open network. */
+ wpa_dbg(wpa_s, MSG_DEBUG, "OWE: transition mode BSSID: " MACSTR
+ " SSID: %s", MAC2STR(bssid), wpa_ssid_txt(pos, ssid_len));
+ *ret_ssid = pos;
+ *ret_ssid_len = ssid_len;
+
+ if (bss->ssid_len > 0)
+ return;
+
+ open_bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
+ if (!open_bss)
+ return;
+ if (ssid_len != open_bss->ssid_len ||
+ os_memcmp(pos, open_bss->ssid, ssid_len) != 0) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "OWE: transition mode SSID mismatch: %s",
+ wpa_ssid_txt(open_bss->ssid, open_bss->ssid_len));
+ return;
+ }
+
+ owe = wpa_bss_get_vendor_ie(open_bss, OWE_IE_VENDOR_TYPE);
+ if (!owe || wpa_bss_get_ie(open_bss, WLAN_EID_RSN)) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "OWE: transition mode open BSS unexpected info");
+ return;
+ }
+
+ pos = owe + 6;
+ end = owe + 2 + owe[1];
+
+ if (end - pos < ETH_ALEN + 1)
+ return;
+ if (os_memcmp(pos, bss->bssid, ETH_ALEN) != 0) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "OWE: transition mode BSSID mismatch: " MACSTR,
+ MAC2STR(pos));
+ return;
+ }
+ pos += ETH_ALEN;
+ ssid_len = *pos++;
+ if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
+ return;
+ wpa_dbg(wpa_s, MSG_DEBUG, "OWE: learned transition mode OWE SSID: %s",
+ wpa_ssid_txt(pos, ssid_len));
+ os_memcpy(bss->ssid, pos, ssid_len);
+ bss->ssid_len = ssid_len;
+#endif /* CONFIG_OWE */
+}
+
+
struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
int i, struct wpa_bss *bss,
struct wpa_ssid *group,
- int only_first_ssid)
+ int only_first_ssid, int debug_print)
{
u8 wpa_ie_len, rsn_ie_len;
int wpa;
struct wpa_blacklist *e;
const u8 *ie;
struct wpa_ssid *ssid;
- int osen;
+ int osen, rsn_osen = 0;
#ifdef CONFIG_MBO
const u8 *assoc_disallow;
#endif /* CONFIG_MBO */
+ const u8 *match_ssid;
+ size_t match_ssid_len;
+ struct wpa_ie_data data;
ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
wpa_ie_len = ie ? ie[1] : 0;
ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
rsn_ie_len = ie ? ie[1] : 0;
+ if (ie && wpa_parse_wpa_ie_rsn(ie, 2 + ie[1], &data) == 0 &&
+ (data.key_mgmt & WPA_KEY_MGMT_OSEN))
+ rsn_osen = 1;
ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
osen = ie != NULL;
- wpa_dbg(wpa_s, MSG_DEBUG, "%d: " MACSTR " ssid='%s' "
- "wpa_ie_len=%u rsn_ie_len=%u caps=0x%x level=%d freq=%d %s%s%s",
- i, MAC2STR(bss->bssid), wpa_ssid_txt(bss->ssid, bss->ssid_len),
- wpa_ie_len, rsn_ie_len, bss->caps, bss->level, bss->freq,
- wpa_bss_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE) ? " wps" : "",
- (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) ||
- wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) ?
- " p2p" : "",
- osen ? " osen=1" : "");
+ if (debug_print) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "%d: " MACSTR
+ " ssid='%s' wpa_ie_len=%u rsn_ie_len=%u caps=0x%x level=%d freq=%d %s%s%s",
+ i, MAC2STR(bss->bssid),
+ wpa_ssid_txt(bss->ssid, bss->ssid_len),
+ wpa_ie_len, rsn_ie_len, bss->caps, bss->level,
+ bss->freq,
+ wpa_bss_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE) ?
+ " wps" : "",
+ (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) ||
+ wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE))
+ ? " p2p" : "",
+ osen ? " osen=1" : "");
+ }
e = wpa_blacklist_get(wpa_s, bss->bssid);
if (e) {
@@ -890,24 +1070,34 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
limit = 0;
}
if (e->count > limit) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - blacklisted "
- "(count=%d limit=%d)", e->count, limit);
+ if (debug_print) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - blacklisted (count=%d limit=%d)",
+ e->count, limit);
+ }
return NULL;
}
}
- if (bss->ssid_len == 0) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID not known");
+ match_ssid = bss->ssid;
+ match_ssid_len = bss->ssid_len;
+ owe_trans_ssid(wpa_s, bss, &match_ssid, &match_ssid_len);
+
+ if (match_ssid_len == 0) {
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID not known");
return NULL;
}
if (disallowed_bssid(wpa_s, bss->bssid)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - BSSID disallowed");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG, " skip - BSSID disallowed");
return NULL;
}
- if (disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID disallowed");
+ if (disallowed_ssid(wpa_s, match_ssid, match_ssid_len)) {
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID disallowed");
return NULL;
}
@@ -918,21 +1108,25 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
int res;
if (wpas_network_disabled(wpa_s, ssid)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - disabled");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG, " skip - disabled");
continue;
}
res = wpas_temp_disabled(wpa_s, ssid);
if (res > 0) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - disabled "
- "temporarily for %d second(s)", res);
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - disabled temporarily for %d second(s)",
+ res);
continue;
}
#ifdef CONFIG_WPS
if ((ssid->key_mgmt & WPA_KEY_MGMT_WPS) && e && e->count > 0) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - blacklisted "
- "(WPS)");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - blacklisted (WPS)");
continue;
}
@@ -956,15 +1150,19 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
check_ssid = 0;
if (check_ssid &&
- (bss->ssid_len != ssid->ssid_len ||
- os_memcmp(bss->ssid, ssid->ssid, bss->ssid_len) != 0)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID mismatch");
+ (match_ssid_len != ssid->ssid_len ||
+ os_memcmp(match_ssid, ssid->ssid, match_ssid_len) != 0)) {
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - SSID mismatch");
continue;
}
if (ssid->bssid_set &&
os_memcmp(bss->bssid, ssid->bssid, ETH_ALEN) != 0) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - BSSID mismatch");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - BSSID mismatch");
continue;
}
@@ -972,8 +1170,9 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
if (ssid->num_bssid_blacklist &&
addr_in_list(bss->bssid, ssid->bssid_blacklist,
ssid->num_bssid_blacklist)) {
- wpa_dbg(wpa_s, MSG_DEBUG,
- " skip - BSSID blacklisted");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - BSSID blacklisted");
continue;
}
@@ -981,79 +1180,108 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
if (ssid->num_bssid_whitelist &&
!addr_in_list(bss->bssid, ssid->bssid_whitelist,
ssid->num_bssid_whitelist)) {
- wpa_dbg(wpa_s, MSG_DEBUG,
- " skip - BSSID not in whitelist");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - BSSID not in whitelist");
continue;
}
- if (!wpa_supplicant_ssid_bss_match(wpa_s, ssid, bss))
+ if (!wpa_supplicant_ssid_bss_match(wpa_s, ssid, bss,
+ debug_print))
continue;
if (!osen && !wpa &&
!(ssid->key_mgmt & WPA_KEY_MGMT_NONE) &&
!(ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
+ !(ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
!(ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - non-WPA network "
- "not allowed");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - non-WPA network not allowed");
continue;
}
if (wpa && !wpa_key_mgmt_wpa(ssid->key_mgmt) &&
has_wep_key(ssid)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - ignore WPA/WPA2 AP for WEP network block");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - ignore WPA/WPA2 AP for WEP network block");
continue;
}
- if ((ssid->key_mgmt & WPA_KEY_MGMT_OSEN) && !osen) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - non-OSEN network "
- "not allowed");
+ if ((ssid->key_mgmt & WPA_KEY_MGMT_OSEN) && !osen &&
+ !rsn_osen) {
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - non-OSEN network not allowed");
continue;
}
if (!wpa_supplicant_match_privacy(bss, ssid)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - privacy "
- "mismatch");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - privacy mismatch");
continue;
}
if (ssid->mode != IEEE80211_MODE_MESH && !bss_is_ess(bss) &&
!bss_is_pbss(bss)) {
- wpa_dbg(wpa_s, MSG_DEBUG,
- " skip - not ESS, PBSS, or MBSS");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - not ESS, PBSS, or MBSS");
continue;
}
if (ssid->pbss != 2 && ssid->pbss != bss_is_pbss(bss)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - PBSS mismatch (ssid %d bss %d)",
- ssid->pbss, bss_is_pbss(bss));
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - PBSS mismatch (ssid %d bss %d)",
+ ssid->pbss, bss_is_pbss(bss));
continue;
}
if (!freq_allowed(ssid->freq_list, bss->freq)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - frequency not "
- "allowed");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - frequency not allowed");
continue;
}
#ifdef CONFIG_MESH
if (ssid->mode == IEEE80211_MODE_MESH && ssid->frequency > 0 &&
ssid->frequency != bss->freq) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - frequency not allowed (mesh)");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - frequency not allowed (mesh)");
continue;
}
#endif /* CONFIG_MESH */
- if (!rate_match(wpa_s, bss)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - rate sets do "
- "not match");
+ if (!rate_match(wpa_s, bss, debug_print)) {
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - rate sets do not match");
continue;
}
+#ifndef CONFIG_IBSS_RSN
+ if (ssid->mode == WPAS_MODE_IBSS &&
+ !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE |
+ WPA_KEY_MGMT_WPA_NONE))) {
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - IBSS RSN not supported in the build");
+ continue;
+ }
+#endif /* !CONFIG_IBSS_RSN */
+
#ifdef CONFIG_P2P
if (ssid->p2p_group &&
!wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) &&
!wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - no P2P IE seen");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - no P2P IE seen");
continue;
}
@@ -1063,20 +1291,26 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
ie = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
if (ie == NULL) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - no P2P element");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - no P2P element");
continue;
}
p2p_ie = wpa_bss_get_vendor_ie_multi(
bss, P2P_IE_VENDOR_TYPE);
if (p2p_ie == NULL) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - could not fetch P2P element");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - could not fetch P2P element");
continue;
}
if (p2p_parse_dev_addr_in_p2p_ie(p2p_ie, dev_addr) < 0
|| os_memcmp(dev_addr, ssid->go_p2p_dev_addr,
ETH_ALEN) != 0) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - no matching GO P2P Device Address in P2P element");
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - no matching GO P2P Device Address in P2P element");
wpabuf_free(p2p_ie);
continue;
}
@@ -1096,8 +1330,9 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
os_reltime_sub(&wpa_s->scan_min_time,
&bss->last_update, &diff);
- wpa_dbg(wpa_s, MSG_DEBUG,
- " skip - scan result not recent enough (%u.%06u seconds too old)",
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - scan result not recent enough (%u.%06u seconds too old)",
(unsigned int) diff.sec,
(unsigned int) diff.usec);
continue;
@@ -1110,15 +1345,17 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
assoc_disallow = wpas_mbo_get_bss_attr(
bss, MBO_ATTR_ID_ASSOC_DISALLOW);
if (assoc_disallow && assoc_disallow[1] >= 1) {
- wpa_dbg(wpa_s, MSG_DEBUG,
- " skip - MBO association disallowed (reason %u)",
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - MBO association disallowed (reason %u)",
assoc_disallow[2]);
continue;
}
- if (wpa_is_bss_tmp_disallowed(wpa_s, bss->bssid)) {
- wpa_dbg(wpa_s, MSG_DEBUG,
- " skip - MBO retry delay has not passed yet");
+ if (wpa_is_bss_tmp_disallowed(wpa_s, bss)) {
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - AP temporarily disallowed");
continue;
}
#ifdef CONFIG_TESTING_OPTIONS
@@ -1126,6 +1363,19 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_TESTING_OPTIONS */
#endif /* CONFIG_MBO */
+#ifdef CONFIG_DPP
+ if ((ssid->key_mgmt & WPA_KEY_MGMT_DPP) &&
+ !wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, ssid) &&
+ (!ssid->dpp_connector ||
+ !ssid->dpp_netaccesskey ||
+ !ssid->dpp_csign)) {
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - no PMKSA entry for DPP");
+ continue;
+ }
+#endif /* CONFIG_DPP */
+
/* Matching configuration found */
return ssid;
}
@@ -1143,6 +1393,25 @@ wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s,
{
unsigned int i;
+ if (wpa_s->current_ssid) {
+ struct wpa_ssid *ssid;
+
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Scan results matching the currently selected network");
+ for (i = 0; i < wpa_s->last_scan_res_used; i++) {
+ struct wpa_bss *bss = wpa_s->last_scan_res[i];
+
+ ssid = wpa_scan_res_match(wpa_s, i, bss, group,
+ only_first_ssid, 0);
+ if (ssid != wpa_s->current_ssid)
+ continue;
+ wpa_dbg(wpa_s, MSG_DEBUG, "%u: " MACSTR
+ " freq=%d level=%d snr=%d est_throughput=%u",
+ i, MAC2STR(bss->bssid), bss->freq, bss->level,
+ bss->snr, bss->est_throughput);
+ }
+ }
+
if (only_first_ssid)
wpa_dbg(wpa_s, MSG_DEBUG, "Try to find BSS matching pre-selected network id=%d",
group->id);
@@ -1152,8 +1421,11 @@ wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s,
for (i = 0; i < wpa_s->last_scan_res_used; i++) {
struct wpa_bss *bss = wpa_s->last_scan_res[i];
+
+ wpa_s->owe_transition_select = 1;
*selected_ssid = wpa_scan_res_match(wpa_s, i, bss, group,
- only_first_ssid);
+ only_first_ssid, 1);
+ wpa_s->owe_transition_select = 0;
if (!*selected_ssid)
continue;
wpa_dbg(wpa_s, MSG_DEBUG, " selected BSS " MACSTR
@@ -1334,6 +1606,17 @@ wpa_supplicant_pick_new_network(struct wpa_supplicant *wpa_s)
{
if (wpas_network_disabled(wpa_s, ssid))
continue;
+#ifndef CONFIG_IBSS_RSN
+ if (ssid->mode == WPAS_MODE_IBSS &&
+ !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE |
+ WPA_KEY_MGMT_WPA_NONE))) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "IBSS RSN not supported in the build - cannot use the profile for SSID '%s'",
+ wpa_ssid_txt(ssid->ssid,
+ ssid->ssid_len));
+ continue;
+ }
+#endif /* !CONFIG_IBSS_RSN */
if (ssid->mode == IEEE80211_MODE_IBSS ||
ssid->mode == IEEE80211_MODE_AP ||
ssid->mode == IEEE80211_MODE_MESH)
@@ -1377,8 +1660,9 @@ static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s,
{
struct wpa_bss *current_bss = NULL;
#ifndef CONFIG_NO_ROAMING
- int min_diff;
+ int min_diff, diff;
int to_5ghz;
+ int cur_est, sel_est;
#endif /* CONFIG_NO_ROAMING */
if (wpa_s->reassociate)
@@ -1412,12 +1696,13 @@ static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s,
#ifndef CONFIG_NO_ROAMING
wpa_dbg(wpa_s, MSG_DEBUG, "Considering within-ESS reassociation");
wpa_dbg(wpa_s, MSG_DEBUG, "Current BSS: " MACSTR
- " level=%d snr=%d est_throughput=%u",
- MAC2STR(current_bss->bssid), current_bss->level,
+ " freq=%d level=%d snr=%d est_throughput=%u",
+ MAC2STR(current_bss->bssid),
+ current_bss->freq, current_bss->level,
current_bss->snr, current_bss->est_throughput);
wpa_dbg(wpa_s, MSG_DEBUG, "Selected BSS: " MACSTR
- " level=%d snr=%d est_throughput=%u",
- MAC2STR(selected->bssid), selected->level,
+ " freq=%d level=%d snr=%d est_throughput=%u",
+ MAC2STR(selected->bssid), selected->freq, selected->level,
selected->snr, selected->est_throughput);
if (wpa_s->current_ssid->bssid_set &&
@@ -1443,6 +1728,14 @@ static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s,
return 0;
}
+ if (current_bss->est_throughput > selected->est_throughput + 5000) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Skip roam - Current BSS has better estimated throughput");
+ return 0;
+ }
+
+ cur_est = current_bss->est_throughput;
+ sel_est = selected->est_throughput;
min_diff = 2;
if (current_bss->level < 0) {
if (current_bss->level < -85)
@@ -1455,20 +1748,42 @@ static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s,
min_diff = 4;
else
min_diff = 5;
+ if (cur_est > sel_est * 1.5)
+ min_diff += 10;
+ else if (cur_est > sel_est * 1.2)
+ min_diff += 5;
+ else if (cur_est > sel_est * 1.1)
+ min_diff += 2;
+ else if (cur_est > sel_est)
+ min_diff++;
}
if (to_5ghz) {
+ int reduce = 2;
+
/* Make it easier to move to 5 GHz band */
- if (min_diff > 2)
- min_diff -= 2;
+ if (sel_est > cur_est * 1.5)
+ reduce = 5;
+ else if (sel_est > cur_est * 1.2)
+ reduce = 4;
+ else if (sel_est > cur_est * 1.1)
+ reduce = 3;
+
+ if (min_diff > reduce)
+ min_diff -= reduce;
else
min_diff = 0;
}
- if (abs(current_bss->level - selected->level) < min_diff) {
- wpa_dbg(wpa_s, MSG_DEBUG, "Skip roam - too small difference "
- "in signal level");
+ diff = abs(current_bss->level - selected->level);
+ if (diff < min_diff) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Skip roam - too small difference in signal level (%d < %d)",
+ diff, min_diff);
return 0;
}
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Allow reassociation due to difference in signal level (%d >= %d)",
+ diff, min_diff);
return 1;
#else /* CONFIG_NO_ROAMING */
return 0;
@@ -1476,11 +1791,18 @@ static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s,
}
-/* Return != 0 if no scan results could be fetched or if scan results should not
- * be shared with other virtual interfaces. */
+/*
+ * Return a negative value if no scan results could be fetched or if scan
+ * results should not be shared with other virtual interfaces.
+ * Return 0 if scan results were fetched and may be shared with other
+ * interfaces.
+ * Return 1 if scan results may be shared with other virtual interfaces but may
+ * not trigger any operations.
+ * Return 2 if the interface was removed and cannot be used.
+ */
static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
union wpa_event_data *data,
- int own_request)
+ int own_request, int update_only)
{
struct wpa_scan_results *scan_res = NULL;
int ret = 0;
@@ -1530,6 +1852,11 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
}
#endif /* CONFIG_NO_RANDOM_POOL */
+ if (update_only) {
+ ret = 1;
+ goto scan_work_done;
+ }
+
if (own_request && wpa_s->scan_res_handler &&
!(data && data->scan_info.external_scan)) {
void (*scan_res_handler)(struct wpa_supplicant *wpa_s,
@@ -1538,7 +1865,7 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
scan_res_handler = wpa_s->scan_res_handler;
wpa_s->scan_res_handler = NULL;
scan_res_handler(wpa_s, scan_res);
- ret = -2;
+ ret = 1;
goto scan_work_done;
}
@@ -1579,6 +1906,10 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
if (sme_proc_obss_scan(wpa_s) > 0)
goto scan_work_done;
+ if (own_request && data &&
+ wpas_beacon_rep_scan_process(wpa_s, scan_res, &data->scan_info) > 0)
+ goto scan_work_done;
+
if ((wpa_s->conf->ap_scan == 2 && !wpas_wps_searching(wpa_s)))
goto scan_work_done;
@@ -1641,6 +1972,7 @@ static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s,
if (wpa_s->p2p_mgmt)
return 0; /* no normal connection on p2p_mgmt interface */
+ wpa_s->owe_transition_search = 0;
selected = wpa_supplicant_pick_network(wpa_s, &ssid);
#ifdef CONFIG_MESH
@@ -1674,8 +2006,9 @@ static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s,
if (new_scan)
wpa_supplicant_rsn_preauth_scan_results(wpa_s);
/*
- * Do not notify other virtual radios of scan results since we do not
- * want them to start other associations at the same time.
+ * Do not allow other virtual radios to trigger operations based
+ * on these scan results since we do not want them to start
+ * other associations at the same time.
*/
return 1;
} else {
@@ -1741,6 +2074,17 @@ static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s,
return 0;
}
#endif /* CONFIG_WPS */
+#ifdef CONFIG_OWE
+ if (wpa_s->owe_transition_search) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "OWE: Use shorter wait during transition mode search");
+ timeout_sec = 0;
+ timeout_usec = 500000;
+ wpa_supplicant_req_new_scan(wpa_s, timeout_sec,
+ timeout_usec);
+ return 0;
+ }
+#endif /* CONFIG_OWE */
if (wpa_supplicant_req_sched_scan(wpa_s))
wpa_supplicant_req_new_scan(wpa_s, timeout_sec,
timeout_usec);
@@ -1759,7 +2103,7 @@ static int wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
struct wpa_supplicant *ifs;
int res;
- res = _wpa_supplicant_event_scan_results(wpa_s, data, 1);
+ res = _wpa_supplicant_event_scan_results(wpa_s, data, 1, 0);
if (res == 2) {
/*
* Interface may have been removed, so must not dereference
@@ -1767,7 +2111,8 @@ static int wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
*/
return 1;
}
- if (res != 0) {
+
+ if (res < 0) {
/*
* If no scan results could be fetched, then no need to
* notify those interfaces that did not actually request
@@ -1787,7 +2132,10 @@ static int wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
if (ifs != wpa_s) {
wpa_printf(MSG_DEBUG, "%s: Updating scan results from "
"sibling", ifs->ifname);
- _wpa_supplicant_event_scan_results(ifs, data, 0);
+ res = _wpa_supplicant_event_scan_results(ifs, data, 0,
+ res > 0);
+ if (res < 0)
+ return 0;
}
}
@@ -1804,6 +2152,8 @@ int wpa_supplicant_fast_associate(struct wpa_supplicant *wpa_s)
#else /* CONFIG_NO_SCAN_PROCESSING */
struct os_reltime now;
+ wpa_s->ignore_post_flush_scan_res = 0;
+
if (wpa_s->last_scan_res_used == 0)
return -1;
@@ -1934,6 +2284,57 @@ static void interworking_process_assoc_resp(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_INTERWORKING */
+static void multi_ap_process_assoc_resp(struct wpa_supplicant *wpa_s,
+ const u8 *ies, size_t ies_len)
+{
+ struct ieee802_11_elems elems;
+ const u8 *map_sub_elem, *pos;
+ size_t len;
+
+ if (!wpa_s->current_ssid ||
+ !wpa_s->current_ssid->multi_ap_backhaul_sta ||
+ !ies ||
+ ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed)
+ return;
+
+ if (!elems.multi_ap || elems.multi_ap_len < 7) {
+ wpa_printf(MSG_INFO, "AP doesn't support Multi-AP protocol");
+ goto fail;
+ }
+
+ pos = elems.multi_ap + 4;
+ len = elems.multi_ap_len - 4;
+
+ map_sub_elem = get_ie(pos, len, MULTI_AP_SUB_ELEM_TYPE);
+ if (!map_sub_elem || map_sub_elem[1] < 1) {
+ wpa_printf(MSG_INFO, "invalid Multi-AP sub elem type");
+ goto fail;
+ }
+
+ if (!(map_sub_elem[2] & MULTI_AP_BACKHAUL_BSS)) {
+ if ((map_sub_elem[2] & MULTI_AP_FRONTHAUL_BSS) &&
+ wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
+ wpa_printf(MSG_INFO,
+ "WPS active, accepting fronthaul-only BSS");
+ /* Don't set 4addr mode in this case, so just return */
+ return;
+ }
+ wpa_printf(MSG_INFO, "AP doesn't support backhaul BSS");
+ goto fail;
+ }
+
+ if (wpa_drv_set_4addr_mode(wpa_s, 1) < 0) {
+ wpa_printf(MSG_ERROR, "Failed to set 4addr mode");
+ goto fail;
+ }
+ wpa_s->enabled_4addr_mode = 1;
+ return;
+
+fail:
+ wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
+}
+
+
#ifdef CONFIG_FST
static int wpas_fst_update_mbie(struct wpa_supplicant *wpa_s,
const u8 *ie, size_t ie_len)
@@ -1983,9 +2384,9 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
{
int l, len, found = 0, wpa_found, rsn_found;
const u8 *p;
-#ifdef CONFIG_IEEE80211R
+#if defined(CONFIG_IEEE80211R) || defined(CONFIG_OWE)
u8 bssid[ETH_ALEN];
-#endif /* CONFIG_IEEE80211R */
+#endif /* CONFIG_IEEE80211R || CONFIG_OWE */
wpa_dbg(wpa_s, MSG_DEBUG, "Association info event");
if (data->assoc_info.req_ies)
@@ -2006,6 +2407,13 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
interworking_process_assoc_resp(wpa_s, data->assoc_info.resp_ies,
data->assoc_info.resp_ies_len);
#endif /* CONFIG_INTERWORKING */
+ if (wpa_s->hw_capab == CAPAB_VHT &&
+ get_ie(data->assoc_info.resp_ies,
+ data->assoc_info.resp_ies_len, WLAN_EID_VHT_CAP))
+ wpa_s->ieee80211ac = 1;
+
+ multi_ap_process_assoc_resp(wpa_s, data->assoc_info.resp_ies,
+ data->assoc_info.resp_ies_len);
}
if (data->assoc_info.beacon_ies)
wpa_hexdump(MSG_DEBUG, "beacon_ies",
@@ -2015,6 +2423,26 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
wpa_dbg(wpa_s, MSG_DEBUG, "freq=%u MHz",
data->assoc_info.freq);
+ wpa_s->connection_set = 0;
+ if (data->assoc_info.req_ies && data->assoc_info.resp_ies) {
+ struct ieee802_11_elems req_elems, resp_elems;
+
+ if (ieee802_11_parse_elems(data->assoc_info.req_ies,
+ data->assoc_info.req_ies_len,
+ &req_elems, 0) != ParseFailed &&
+ ieee802_11_parse_elems(data->assoc_info.resp_ies,
+ data->assoc_info.resp_ies_len,
+ &resp_elems, 0) != ParseFailed) {
+ wpa_s->connection_set = 1;
+ wpa_s->connection_ht = req_elems.ht_capabilities &&
+ resp_elems.ht_capabilities;
+ wpa_s->connection_vht = req_elems.vht_capabilities &&
+ resp_elems.vht_capabilities;
+ wpa_s->connection_he = req_elems.he_capabilities &&
+ resp_elems.he_capabilities;
+ }
+ }
+
p = data->assoc_info.req_ies;
l = data->assoc_info.req_ies_len;
@@ -2043,6 +2471,58 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
if (!found && data->assoc_info.req_ies)
wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
+#ifdef CONFIG_FILS
+#ifdef CONFIG_SME
+ if ((wpa_s->sme.auth_alg == WPA_AUTH_ALG_FILS ||
+ wpa_s->sme.auth_alg == WPA_AUTH_ALG_FILS_SK_PFS) &&
+ (!data->assoc_info.resp_frame ||
+ fils_process_assoc_resp(wpa_s->wpa,
+ data->assoc_info.resp_frame,
+ data->assoc_info.resp_frame_len) < 0)) {
+ wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
+ return -1;
+ }
+#endif /* CONFIG_SME */
+
+ /* Additional processing for FILS when SME is in driver */
+ if (wpa_s->auth_alg == WPA_AUTH_ALG_FILS &&
+ !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
+ wpa_sm_set_reset_fils_completed(wpa_s->wpa, 1);
+#endif /* CONFIG_FILS */
+
+#ifdef CONFIG_OWE
+ if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE &&
+ (wpa_drv_get_bssid(wpa_s, bssid) < 0 ||
+ owe_process_assoc_resp(wpa_s->wpa, bssid,
+ data->assoc_info.resp_ies,
+ data->assoc_info.resp_ies_len) < 0)) {
+ wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
+ return -1;
+ }
+#endif /* CONFIG_OWE */
+
+#ifdef CONFIG_DPP2
+ wpa_sm_set_dpp_z(wpa_s->wpa, NULL);
+ if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP && wpa_s->dpp_pfs) {
+ struct ieee802_11_elems elems;
+
+ if (ieee802_11_parse_elems(data->assoc_info.resp_ies,
+ data->assoc_info.resp_ies_len,
+ &elems, 0) == ParseFailed ||
+ !elems.owe_dh)
+ goto no_pfs;
+ if (dpp_pfs_process(wpa_s->dpp_pfs, elems.owe_dh,
+ elems.owe_dh_len) < 0) {
+ wpa_supplicant_deauthenticate(wpa_s,
+ WLAN_REASON_UNSPECIFIED);
+ return -1;
+ }
+
+ wpa_sm_set_dpp_z(wpa_s->wpa, wpa_s->dpp_pfs->secret);
+ }
+no_pfs:
+#endif /* CONFIG_DPP2 */
+
#ifdef CONFIG_IEEE80211R
#ifdef CONFIG_SME
if (wpa_s->sme.auth_alg == WPA_AUTH_ALG_FT) {
@@ -2264,6 +2744,13 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
ft_completed = wpa_ft_is_completed(wpa_s->wpa);
if (data && wpa_supplicant_event_associnfo(wpa_s, data) < 0)
return;
+ /*
+ * FILS authentication can share the same mechanism to mark the
+ * connection fully authenticated, so set ft_completed also based on
+ * FILS result.
+ */
+ if (!ft_completed)
+ ft_completed = wpa_fils_is_completed(wpa_s->wpa);
if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
wpa_dbg(wpa_s, MSG_ERROR, "Failed to get BSSID");
@@ -2274,6 +2761,16 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATED);
if (os_memcmp(bssid, wpa_s->bssid, ETH_ALEN) != 0) {
+ if (os_reltime_initialized(&wpa_s->session_start)) {
+ os_reltime_age(&wpa_s->session_start,
+ &wpa_s->session_length);
+ wpa_s->session_start.sec = 0;
+ wpa_s->session_start.usec = 0;
+ wpas_notify_session_length(wpa_s);
+ } else {
+ wpas_notify_auth_changed(wpa_s);
+ os_get_reltime(&wpa_s->session_start);
+ }
wpa_dbg(wpa_s, MSG_DEBUG, "Associated to a new BSS: BSSID="
MACSTR, MAC2STR(bssid));
new_bss = 1;
@@ -2333,7 +2830,9 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
}
- if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || ft_completed ||
+ if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
+ wpa_s->key_mgmt == WPA_KEY_MGMT_DPP ||
+ wpa_s->key_mgmt == WPA_KEY_MGMT_OWE || ft_completed ||
already_authorized)
eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
/* 802.1X::portControl = Auto */
@@ -2362,8 +2861,17 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
}
wpa_supplicant_cancel_scan(wpa_s);
- if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
- wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
+ if (ft_completed) {
+ /*
+ * FT protocol completed - make sure EAPOL state machine ends
+ * up in authenticated.
+ */
+ wpa_supplicant_cancel_auth_timeout(wpa_s);
+ wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
+ eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
+ eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
+ } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
+ wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
/*
* We are done; the driver will take care of RSN 4-way
* handshake.
@@ -2372,7 +2880,7 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
- } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
+ } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
/*
* The driver will take care of RSN 4-way handshake, so we need
@@ -2380,15 +2888,6 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
* waiting for WPA supplicant.
*/
eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
- } else if (ft_completed) {
- /*
- * FT protocol completed - make sure EAPOL state machine ends
- * up in authenticated.
- */
- wpa_supplicant_cancel_auth_timeout(wpa_s);
- wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
- eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
- eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
}
wpa_s->last_eapol_matches_bssid = 0;
@@ -2397,7 +2896,7 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
struct os_reltime now, age;
os_get_reltime(&now);
os_reltime_sub(&now, &wpa_s->pending_eapol_rx_time, &age);
- if (age.sec == 0 && age.usec < 100000 &&
+ if (age.sec == 0 && age.usec < 200000 &&
os_memcmp(wpa_s->pending_eapol_rx_src, bssid, ETH_ALEN) ==
0) {
wpa_dbg(wpa_s, MSG_DEBUG, "Process pending EAPOL "
@@ -2448,6 +2947,16 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
if (wpa_s->reassoc_same_bss)
wmm_ac_restore_tspecs(wpa_s);
}
+
+#ifdef CONFIG_FILS
+ if (wpa_key_mgmt_fils(wpa_s->key_mgmt)) {
+ struct wpa_bss *bss = wpa_bss_get_bssid(wpa_s, bssid);
+ const u8 *fils_cache_id = wpa_bss_get_fils_cache_id(bss);
+
+ if (fils_cache_id)
+ wpa_sm_set_fils_cache_id(wpa_s->wpa, fils_cache_id);
+ }
+#endif /* CONFIG_FILS */
}
@@ -2624,7 +3133,7 @@ static void wpa_supplicant_event_disassoc_finish(struct wpa_supplicant *wpa_s,
!disallowed_ssid(wpa_s, fast_reconnect->ssid,
fast_reconnect->ssid_len) &&
!wpas_temp_disabled(wpa_s, fast_reconnect_ssid) &&
- !wpa_is_bss_tmp_disallowed(wpa_s, fast_reconnect->bssid)) {
+ !wpa_is_bss_tmp_disallowed(wpa_s, fast_reconnect)) {
#ifndef CONFIG_NO_SCAN_PROCESSING
wpa_dbg(wpa_s, MSG_DEBUG, "Try to reconnect to the same BSS");
if (wpa_supplicant_connect(wpa_s, fast_reconnect,
@@ -2839,18 +3348,6 @@ wpa_supplicant_event_interface_status(struct wpa_supplicant *wpa_s,
}
-#ifdef CONFIG_PEERKEY
-static void
-wpa_supplicant_event_stkstart(struct wpa_supplicant *wpa_s,
- union wpa_event_data *data)
-{
- if (data == NULL)
- return;
- wpa_sm_stkstart(wpa_s->wpa, data->stkstart.peer);
-}
-#endif /* CONFIG_PEERKEY */
-
-
#ifdef CONFIG_TDLS
static void wpa_supplicant_event_tdls(struct wpa_supplicant *wpa_s,
union wpa_event_data *data)
@@ -3209,10 +3706,11 @@ static const char * reg_type_str(enum reg_type type)
}
-static void wpa_supplicant_update_channel_list(
- struct wpa_supplicant *wpa_s, struct channel_list_changed *info)
+void wpa_supplicant_update_channel_list(struct wpa_supplicant *wpa_s,
+ struct channel_list_changed *info)
{
struct wpa_supplicant *ifs;
+ u8 dfs_domain;
/*
* To allow backwards compatibility with higher level layers that
@@ -3223,10 +3721,13 @@ static void wpa_supplicant_update_channel_list(
for (ifs = wpa_s; ifs->parent && ifs != ifs->parent; ifs = ifs->parent)
;
- wpa_msg(ifs, MSG_INFO, WPA_EVENT_REGDOM_CHANGE "init=%s type=%s%s%s",
- reg_init_str(info->initiator), reg_type_str(info->type),
- info->alpha2[0] ? " alpha2=" : "",
- info->alpha2[0] ? info->alpha2 : "");
+ if (info) {
+ wpa_msg(ifs, MSG_INFO,
+ WPA_EVENT_REGDOM_CHANGE "init=%s type=%s%s%s",
+ reg_init_str(info->initiator), reg_type_str(info->type),
+ info->alpha2[0] ? " alpha2=" : "",
+ info->alpha2[0] ? info->alpha2 : "");
+ }
if (wpa_s->drv_priv == NULL)
return; /* Ignore event during drv initialization */
@@ -3237,7 +3738,7 @@ static void wpa_supplicant_update_channel_list(
ifs->ifname);
free_hw_features(ifs);
ifs->hw.modes = wpa_drv_get_hw_feature_data(
- ifs, &ifs->hw.num_modes, &ifs->hw.flags);
+ ifs, &ifs->hw.num_modes, &ifs->hw.flags, &dfs_domain);
/* Restart PNO/sched_scan with updated channel list */
if (ifs->pno) {
@@ -3312,6 +3813,15 @@ static void wpas_event_rx_mgmt_action(struct wpa_supplicant *wpa_s,
return;
#endif /* CONFIG_GAS */
+#ifdef CONFIG_GAS_SERVER
+ if ((mgmt->u.action.category == WLAN_ACTION_PUBLIC ||
+ mgmt->u.action.category == WLAN_ACTION_PROTECTED_DUAL) &&
+ gas_server_rx(wpa_s->gas_server, mgmt->da, mgmt->sa, mgmt->bssid,
+ mgmt->u.action.category,
+ payload, plen, freq) == 0)
+ return;
+#endif /* CONFIG_GAS_SERVER */
+
#ifdef CONFIG_TDLS
if (category == WLAN_ACTION_PUBLIC && plen >= 4 &&
payload[0] == WLAN_TDLS_DISCOVERY_RESPONSE) {
@@ -3340,6 +3850,7 @@ static void wpas_event_rx_mgmt_action(struct wpa_supplicant *wpa_s,
if (category == WLAN_ACTION_RADIO_MEASUREMENT &&
payload[0] == WLAN_RRM_RADIO_MEASUREMENT_REQUEST) {
wpas_rrm_handle_radio_measurement_request(wpa_s, mgmt->sa,
+ mgmt->da,
payload + 1,
plen - 1);
return;
@@ -3366,6 +3877,18 @@ static void wpas_event_rx_mgmt_action(struct wpa_supplicant *wpa_s,
}
#endif /* CONFIG_FST */
+#ifdef CONFIG_DPP
+ if (category == WLAN_ACTION_PUBLIC && plen >= 5 &&
+ payload[0] == WLAN_PA_VENDOR_SPECIFIC &&
+ WPA_GET_BE24(&payload[1]) == OUI_WFA &&
+ payload[4] == DPP_OUI_TYPE) {
+ payload++;
+ plen--;
+ wpas_dpp_rx_action(wpa_s, mgmt->sa, payload, plen, freq);
+ return;
+ }
+#endif /* CONFIG_DPP */
+
wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid,
category, payload, plen, freq);
if (wpa_s->ifmsh)
@@ -3406,23 +3929,252 @@ static void wpa_supplicant_notify_avoid_freq(struct wpa_supplicant *wpa_s,
}
-static void wpa_supplicant_event_assoc_auth(struct wpa_supplicant *wpa_s,
- union wpa_event_data *data)
+static void wpa_supplicant_event_port_authorized(struct wpa_supplicant *wpa_s)
{
- wpa_dbg(wpa_s, MSG_DEBUG,
- "Connection authorized by device, previous state %d",
- wpa_s->wpa_state);
if (wpa_s->wpa_state == WPA_ASSOCIATED) {
wpa_supplicant_cancel_auth_timeout(wpa_s);
wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
}
+}
+
+
+static unsigned int wpas_event_cac_ms(const struct wpa_supplicant *wpa_s,
+ int freq)
+{
+ size_t i;
+ int j;
+
+ for (i = 0; i < wpa_s->hw.num_modes; i++) {
+ const struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i];
+
+ for (j = 0; j < mode->num_channels; j++) {
+ const struct hostapd_channel_data *chan;
+
+ chan = &mode->channels[j];
+ if (chan->freq == freq)
+ return chan->dfs_cac_ms;
+ }
+ }
+
+ return 0;
+}
+
+
+static void wpas_event_dfs_cac_started(struct wpa_supplicant *wpa_s,
+ struct dfs_event *radar)
+{
+#if defined(NEED_AP_MLME) && defined(CONFIG_AP)
+ if (wpa_s->ap_iface || wpa_s->ifmsh) {
+ wpas_ap_event_dfs_cac_started(wpa_s, radar);
+ } else
+#endif /* NEED_AP_MLME && CONFIG_AP */
+ {
+ unsigned int cac_time = wpas_event_cac_ms(wpa_s, radar->freq);
+
+ cac_time /= 1000; /* convert from ms to sec */
+ if (!cac_time)
+ cac_time = 10 * 60; /* max timeout: 10 minutes */
+
+ /* Restart auth timeout: CAC time added to initial timeout */
+ wpas_auth_timeout_restart(wpa_s, cac_time);
+ }
+}
+
+
+static void wpas_event_dfs_cac_finished(struct wpa_supplicant *wpa_s,
+ struct dfs_event *radar)
+{
+#if defined(NEED_AP_MLME) && defined(CONFIG_AP)
+ if (wpa_s->ap_iface || wpa_s->ifmsh) {
+ wpas_ap_event_dfs_cac_finished(wpa_s, radar);
+ } else
+#endif /* NEED_AP_MLME && CONFIG_AP */
+ {
+ /* Restart auth timeout with original value after CAC is
+ * finished */
+ wpas_auth_timeout_restart(wpa_s, 0);
+ }
+}
+
+
+static void wpas_event_dfs_cac_aborted(struct wpa_supplicant *wpa_s,
+ struct dfs_event *radar)
+{
+#if defined(NEED_AP_MLME) && defined(CONFIG_AP)
+ if (wpa_s->ap_iface || wpa_s->ifmsh) {
+ wpas_ap_event_dfs_cac_aborted(wpa_s, radar);
+ } else
+#endif /* NEED_AP_MLME && CONFIG_AP */
+ {
+ /* Restart auth timeout with original value after CAC is
+ * aborted */
+ wpas_auth_timeout_restart(wpa_s, 0);
+ }
+}
+
+
+static void wpa_supplicant_event_assoc_auth(struct wpa_supplicant *wpa_s,
+ union wpa_event_data *data)
+{
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Connection authorized by device, previous state %d",
+ wpa_s->wpa_state);
+
+ wpa_supplicant_event_port_authorized(wpa_s);
+
wpa_sm_set_rx_replay_ctr(wpa_s->wpa, data->assoc_info.key_replay_ctr);
wpa_sm_set_ptk_kck_kek(wpa_s->wpa, data->assoc_info.ptk_kck,
data->assoc_info.ptk_kck_len,
data->assoc_info.ptk_kek,
data->assoc_info.ptk_kek_len);
+#ifdef CONFIG_FILS
+ if (wpa_s->auth_alg == WPA_AUTH_ALG_FILS) {
+ struct wpa_bss *bss = wpa_bss_get_bssid(wpa_s, wpa_s->bssid);
+ const u8 *fils_cache_id = wpa_bss_get_fils_cache_id(bss);
+
+ /* Update ERP next sequence number */
+ eapol_sm_update_erp_next_seq_num(
+ wpa_s->eapol, data->assoc_info.fils_erp_next_seq_num);
+
+ if (data->assoc_info.fils_pmk && data->assoc_info.fils_pmkid) {
+ /* Add the new PMK and PMKID to the PMKSA cache */
+ wpa_sm_pmksa_cache_add(wpa_s->wpa,
+ data->assoc_info.fils_pmk,
+ data->assoc_info.fils_pmk_len,
+ data->assoc_info.fils_pmkid,
+ wpa_s->bssid, fils_cache_id);
+ } else if (data->assoc_info.fils_pmkid) {
+ /* Update the current PMKSA used for this connection */
+ pmksa_cache_set_current(wpa_s->wpa,
+ data->assoc_info.fils_pmkid,
+ NULL, NULL, 0, NULL, 0);
+ }
+ }
+#endif /* CONFIG_FILS */
+}
+
+
+static void wpas_event_assoc_reject(struct wpa_supplicant *wpa_s,
+ union wpa_event_data *data)
+{
+ const u8 *bssid = data->assoc_reject.bssid;
+
+ if (!bssid || is_zero_ether_addr(bssid))
+ bssid = wpa_s->pending_bssid;
+
+ if (data->assoc_reject.bssid)
+ wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT
+ "bssid=" MACSTR " status_code=%u%s%s%s",
+ MAC2STR(data->assoc_reject.bssid),
+ data->assoc_reject.status_code,
+ data->assoc_reject.timed_out ? " timeout" : "",
+ data->assoc_reject.timeout_reason ? "=" : "",
+ data->assoc_reject.timeout_reason ?
+ data->assoc_reject.timeout_reason : "");
+ else
+ wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT
+ "status_code=%u%s%s%s",
+ data->assoc_reject.status_code,
+ data->assoc_reject.timed_out ? " timeout" : "",
+ data->assoc_reject.timeout_reason ? "=" : "",
+ data->assoc_reject.timeout_reason ?
+ data->assoc_reject.timeout_reason : "");
+ wpa_s->assoc_status_code = data->assoc_reject.status_code;
+ wpas_notify_assoc_status_code(wpa_s);
+
+#ifdef CONFIG_OWE
+ if (data->assoc_reject.status_code ==
+ WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED &&
+ wpa_s->key_mgmt == WPA_KEY_MGMT_OWE &&
+ wpa_s->current_ssid &&
+ wpa_s->current_ssid->owe_group == 0 &&
+ wpa_s->last_owe_group != 21) {
+ struct wpa_ssid *ssid = wpa_s->current_ssid;
+ struct wpa_bss *bss = wpa_s->current_bss;
+
+ if (!bss) {
+ bss = wpa_supplicant_get_new_bss(wpa_s, bssid);
+ if (!bss) {
+ wpas_connection_failed(wpa_s, bssid);
+ wpa_supplicant_mark_disassoc(wpa_s);
+ return;
+ }
+ }
+ wpa_printf(MSG_DEBUG, "OWE: Try next supported DH group");
+ wpas_connect_work_done(wpa_s);
+ wpa_supplicant_mark_disassoc(wpa_s);
+ wpa_supplicant_connect(wpa_s, bss, ssid);
+ return;
+ }
+#endif /* CONFIG_OWE */
+
+#ifdef CONFIG_MBO
+ if (data->assoc_reject.status_code ==
+ WLAN_STATUS_DENIED_POOR_CHANNEL_CONDITIONS &&
+ wpa_s->current_bss && data->assoc_reject.bssid &&
+ data->assoc_reject.resp_ies) {
+ const u8 *rssi_rej;
+
+ rssi_rej = mbo_get_attr_from_ies(
+ data->assoc_reject.resp_ies,
+ data->assoc_reject.resp_ies_len,
+ OCE_ATTR_ID_RSSI_BASED_ASSOC_REJECT);
+ if (rssi_rej && rssi_rej[1] == 2) {
+ wpa_printf(MSG_DEBUG,
+ "OCE: RSSI-based association rejection from "
+ MACSTR " (Delta RSSI: %u, Retry Delay: %u)",
+ MAC2STR(data->assoc_reject.bssid),
+ rssi_rej[2], rssi_rej[3]);
+ wpa_bss_tmp_disallow(wpa_s,
+ data->assoc_reject.bssid,
+ rssi_rej[3],
+ rssi_rej[2] +
+ wpa_s->current_bss->level);
+ }
+ }
+#endif /* CONFIG_MBO */
+
+ if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) {
+ sme_event_assoc_reject(wpa_s, data);
+ return;
+ }
+
+ /* Driver-based SME cases */
+
+#ifdef CONFIG_SAE
+ if (wpa_s->current_ssid &&
+ wpa_key_mgmt_sae(wpa_s->current_ssid->key_mgmt) &&
+ !data->assoc_reject.timed_out) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "SAE: Drop PMKSA cache entry");
+ wpa_sm_aborted_cached(wpa_s->wpa);
+ wpa_sm_pmksa_cache_flush(wpa_s->wpa, wpa_s->current_ssid);
+ }
+#endif /* CONFIG_SAE */
+
+#ifdef CONFIG_DPP
+ if (wpa_s->current_ssid &&
+ wpa_s->current_ssid->key_mgmt == WPA_KEY_MGMT_DPP &&
+ !data->assoc_reject.timed_out) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "DPP: Drop PMKSA cache entry");
+ wpa_sm_aborted_cached(wpa_s->wpa);
+ wpa_sm_pmksa_cache_flush(wpa_s->wpa, wpa_s->current_ssid);
+ }
+#endif /* CONFIG_DPP */
+
+#ifdef CONFIG_FILS
+ /* Update ERP next sequence number */
+ if (wpa_s->auth_alg == WPA_AUTH_ALG_FILS) {
+ eapol_sm_update_erp_next_seq_num(
+ wpa_s->eapol,
+ data->assoc_reject.fils_erp_next_seq_num);
+ fils_connection_failure(wpa_s);
+ }
+#endif /* CONFIG_FILS */
+
+ wpas_connection_failed(wpa_s, bssid);
+ wpa_supplicant_mark_disassoc(wpa_s);
}
@@ -3431,6 +4183,9 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
{
struct wpa_supplicant *wpa_s = ctx;
int resched;
+#ifndef CONFIG_NO_STDOUT_DEBUG
+ int level = MSG_DEBUG;
+#endif /* CONFIG_NO_STDOUT_DEBUG */
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED &&
event != EVENT_INTERFACE_ENABLED &&
@@ -3444,9 +4199,6 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
}
#ifndef CONFIG_NO_STDOUT_DEBUG
-{
- int level = MSG_DEBUG;
-
if (event == EVENT_RX_MGMT && data->rx_mgmt.frame_len >= 24) {
const struct ieee80211_hdr *hdr;
u16 fc;
@@ -3459,7 +4211,6 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
wpa_dbg(wpa_s, level, "Event %s (%d) received",
event_to_string(event), event);
-}
#endif /* CONFIG_NO_STDOUT_DEBUG */
switch (event) {
@@ -3471,6 +4222,8 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
"FST: MB IEs updated from auth IE");
#endif /* CONFIG_FST */
sme_event_auth(wpa_s, data);
+ wpa_s->auth_status_code = data->auth.status_code;
+ wpas_notify_auth_status_code(wpa_s);
break;
case EVENT_ASSOC:
#ifdef CONFIG_TESTING_OPTIONS
@@ -3479,9 +4232,18 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
"EVENT_ASSOC - ignore_auth_resp active!");
break;
}
+ if (wpa_s->testing_resend_assoc) {
+ wpa_printf(MSG_INFO,
+ "EVENT_DEAUTH - testing_resend_assoc");
+ break;
+ }
#endif /* CONFIG_TESTING_OPTIONS */
wpa_supplicant_event_assoc(wpa_s, data);
- if (data && data->assoc_info.authorized)
+ wpa_s->assoc_status_code = WLAN_STATUS_SUCCESS;
+ if (data &&
+ (data->assoc_info.authorized ||
+ (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
+ wpa_fils_is_completed(wpa_s->wpa))))
wpa_supplicant_event_assoc_auth(wpa_s, data);
if (data) {
wpa_msg(wpa_s, MSG_INFO,
@@ -3500,6 +4262,11 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
"EVENT_DEAUTH - ignore_auth_resp active!");
break;
}
+ if (wpa_s->testing_resend_assoc) {
+ wpa_printf(MSG_INFO,
+ "EVENT_DEAUTH - testing_resend_assoc");
+ break;
+ }
#endif /* CONFIG_TESTING_OPTIONS */
wpas_event_deauth(wpa_s,
data ? &data->deauth_info : NULL);
@@ -3572,11 +4339,6 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
case EVENT_PMKID_CANDIDATE:
wpa_supplicant_event_pmkid_candidate(wpa_s, data);
break;
-#ifdef CONFIG_PEERKEY
- case EVENT_STKSTART:
- wpa_supplicant_event_stkstart(wpa_s, data);
- break;
-#endif /* CONFIG_PEERKEY */
#ifdef CONFIG_TDLS
case EVENT_TDLS:
wpa_supplicant_event_tdls(wpa_s, data);
@@ -3598,28 +4360,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
break;
#endif /* CONFIG_IBSS_RSN */
case EVENT_ASSOC_REJECT:
- if (data->assoc_reject.bssid)
- wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT
- "bssid=" MACSTR " status_code=%u%s",
- MAC2STR(data->assoc_reject.bssid),
- data->assoc_reject.status_code,
- data->assoc_reject.timed_out ? " timeout" : "");
- else
- wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT
- "status_code=%u%s",
- data->assoc_reject.status_code,
- data->assoc_reject.timed_out ? " timeout" : "");
- wpa_s->assoc_status_code = data->assoc_reject.status_code;
- wpas_notify_assoc_status_code(wpa_s);
- if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)
- sme_event_assoc_reject(wpa_s, data);
- else {
- const u8 *bssid = data->assoc_reject.bssid;
- if (bssid == NULL || is_zero_ether_addr(bssid))
- bssid = wpa_s->pending_bssid;
- wpas_connection_failed(wpa_s, bssid);
- wpa_supplicant_mark_disassoc(wpa_s);
- }
+ wpas_event_assoc_reject(wpa_s, data);
break;
case EVENT_AUTH_TIMED_OUT:
/* It is possible to get this event from earlier connection */
@@ -3721,6 +4462,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
ap_rx_from_unknown_sta(wpa_s, data->rx_from_unknown.addr,
data->rx_from_unknown.wds);
break;
+#endif /* CONFIG_AP */
case EVENT_CH_SWITCH:
if (!data || !wpa_s->current_ssid)
break;
@@ -3737,8 +4479,10 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
wpa_s->assoc_freq = data->ch_switch.freq;
wpa_s->current_ssid->frequency = data->ch_switch.freq;
+#ifdef CONFIG_AP
if (wpa_s->current_ssid->mode == WPAS_MODE_AP ||
wpa_s->current_ssid->mode == WPAS_MODE_P2P_GO ||
+ wpa_s->current_ssid->mode == WPAS_MODE_MESH ||
wpa_s->current_ssid->mode ==
WPAS_MODE_P2P_GROUP_FORMATION) {
wpas_ap_ch_switch(wpa_s, data->ch_switch.freq,
@@ -3748,14 +4492,28 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
data->ch_switch.cf1,
data->ch_switch.cf2);
}
+#endif /* CONFIG_AP */
+#ifdef CONFIG_IEEE80211W
+ sme_event_ch_switch(wpa_s);
+#endif /* CONFIG_IEEE80211W */
wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_CS);
+ wnm_clear_coloc_intf_reporting(wpa_s);
break;
+#ifdef CONFIG_AP
#ifdef NEED_AP_MLME
case EVENT_DFS_RADAR_DETECTED:
if (data)
- wpas_event_dfs_radar_detected(wpa_s, &data->dfs_event);
+ wpas_ap_event_dfs_radar_detected(wpa_s,
+ &data->dfs_event);
break;
+ case EVENT_DFS_NOP_FINISHED:
+ if (data)
+ wpas_ap_event_dfs_cac_nop_finished(wpa_s,
+ &data->dfs_event);
+ break;
+#endif /* NEED_AP_MLME */
+#endif /* CONFIG_AP */
case EVENT_DFS_CAC_STARTED:
if (data)
wpas_event_dfs_cac_started(wpa_s, &data->dfs_event);
@@ -3768,13 +4526,6 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
if (data)
wpas_event_dfs_cac_aborted(wpa_s, &data->dfs_event);
break;
- case EVENT_DFS_NOP_FINISHED:
- if (data)
- wpas_event_dfs_cac_nop_finished(wpa_s,
- &data->dfs_event);
- break;
-#endif /* NEED_AP_MLME */
-#endif /* CONFIG_AP */
case EVENT_RX_MGMT: {
u16 fc, stype;
const struct ieee80211_mgmt *mgmt;
@@ -3846,6 +4597,16 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
break;
}
+#ifdef CONFIG_SAE
+ if (stype == WLAN_FC_STYPE_AUTH &&
+ !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
+ (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) {
+ sme_external_auth_mgmt_rx(
+ wpa_s, data->rx_mgmt.frame,
+ data->rx_mgmt.frame_len);
+ break;
+ }
+#endif /* CONFIG_SAE */
wpa_dbg(wpa_s, MSG_DEBUG, "AP: ignore received "
"management frame in non-AP mode");
break;
@@ -3910,6 +4671,10 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
#endif /* CONFIG_OFFCHANNEL */
wpas_p2p_cancel_remain_on_channel_cb(
wpa_s, data->remain_on_channel.freq);
+#ifdef CONFIG_DPP
+ wpas_dpp_cancel_remain_on_channel_cb(
+ wpa_s, data->remain_on_channel.freq);
+#endif /* CONFIG_DPP */
break;
case EVENT_EAPOL_RX:
wpa_supplicant_rx_eapol(wpa_s, data->eapol_rx.src,
@@ -3931,6 +4696,9 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
data->signal_change.current_noise,
data->signal_change.current_txrate);
break;
+ case EVENT_INTERFACE_MAC_CHANGED:
+ wpa_supplicant_update_mac_addr(wpa_s);
+ break;
case EVENT_INTERFACE_ENABLED:
wpa_dbg(wpa_s, MSG_DEBUG, "Interface was enabled");
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
@@ -4097,7 +4865,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
break;
case EVENT_WPS_BUTTON_PUSHED:
#ifdef CONFIG_WPS
- wpas_wps_start_pbc(wpa_s, NULL, 0);
+ wpas_wps_start_pbc(wpa_s, NULL, 0, 0);
#endif /* CONFIG_WPS */
break;
case EVENT_AVOID_FREQUENCIES:
@@ -4131,12 +4899,14 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
#endif /* CONFIG_AP */
break;
case EVENT_ACS_CHANNEL_SELECTED:
+#ifdef CONFIG_AP
#ifdef CONFIG_ACS
if (!wpa_s->ap_iface)
break;
hostapd_acs_channel_selected(wpa_s->ap_iface->bss[0],
&data->acs_selected_channels);
#endif /* CONFIG_ACS */
+#endif /* CONFIG_AP */
break;
case EVENT_P2P_LO_STOP:
#ifdef CONFIG_P2P
@@ -4146,6 +4916,36 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
data->p2p_lo_stop.reason_code);
#endif /* CONFIG_P2P */
break;
+ case EVENT_BEACON_LOSS:
+ if (!wpa_s->current_bss || !wpa_s->current_ssid)
+ break;
+ wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_BEACON_LOSS);
+ bgscan_notify_beacon_loss(wpa_s);
+ break;
+ case EVENT_EXTERNAL_AUTH:
+#ifdef CONFIG_SAE
+ if (!wpa_s->current_ssid) {
+ wpa_printf(MSG_DEBUG, "SAE: current_ssid is NULL");
+ break;
+ }
+ sme_external_auth_trigger(wpa_s, data);
+#endif /* CONFIG_SAE */
+ break;
+ case EVENT_PORT_AUTHORIZED:
+ wpa_supplicant_event_port_authorized(wpa_s);
+ break;
+ case EVENT_STATION_OPMODE_CHANGED:
+#ifdef CONFIG_AP
+ if (!wpa_s->ap_iface || !data)
+ break;
+
+ hostapd_event_sta_opmode_changed(wpa_s->ap_iface->bss[0],
+ data->sta_opmode.addr,
+ data->sta_opmode.smps_mode,
+ data->sta_opmode.chan_width,
+ data->sta_opmode.rx_nss);
+#endif /* CONFIG_AP */
+ break;
default:
wpa_msg(wpa_s, MSG_INFO, "Unknown event %d", event);
break;
diff --git a/freebsd/contrib/wpa/wpa_supplicant/gas_query.c b/freebsd/contrib/wpa/wpa_supplicant/gas_query.c
index c099bc9a..73f02cbe 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/gas_query.c
+++ b/freebsd/contrib/wpa/wpa_supplicant/gas_query.c
@@ -44,6 +44,7 @@ struct gas_query_pending {
unsigned int wait_comeback:1;
unsigned int offchannel_tx_started:1;
unsigned int retry:1;
+ unsigned int wildcard_bssid:1;
int freq;
u16 status_code;
struct wpabuf *req;
@@ -55,6 +56,7 @@ struct gas_query_pending {
const struct wpabuf *adv_proto,
const struct wpabuf *resp, u16 status_code);
void *ctx;
+ u8 sa[ETH_ALEN];
};
/**
@@ -65,6 +67,9 @@ struct gas_query {
struct dl_list pending; /* struct gas_query_pending */
struct gas_query_pending *current;
struct wpa_radio_work *work;
+ struct os_reltime last_mac_addr_rand;
+ int last_rand_sa_type;
+ u8 rand_addr[ETH_ALEN];
};
@@ -119,6 +124,8 @@ static const char * gas_result_txt(enum gas_query_result result)
return "PEER_ERROR";
case GAS_QUERY_INTERNAL_ERROR:
return "INTERNAL_ERROR";
+ case GAS_QUERY_STOPPED:
+ return "STOPPED";
case GAS_QUERY_DELETED_AT_DEINIT:
return "DELETED_AT_DEINIT";
}
@@ -241,10 +248,17 @@ static void gas_query_tx_status(struct wpa_supplicant *wpa_s,
}
os_get_reltime(&query->last_oper);
- if (result == OFFCHANNEL_SEND_ACTION_SUCCESS) {
+ if (result == OFFCHANNEL_SEND_ACTION_SUCCESS ||
+ result == OFFCHANNEL_SEND_ACTION_NO_ACK) {
eloop_cancel_timeout(gas_query_timeout, gas, query);
- eloop_register_timeout(GAS_QUERY_TIMEOUT_PERIOD, 0,
- gas_query_timeout, gas, query);
+ if (result == OFFCHANNEL_SEND_ACTION_NO_ACK) {
+ wpa_printf(MSG_DEBUG, "GAS: No ACK to GAS request");
+ eloop_register_timeout(0, 250000,
+ gas_query_timeout, gas, query);
+ } else {
+ eloop_register_timeout(GAS_QUERY_TIMEOUT_PERIOD, 0,
+ gas_query_timeout, gas, query);
+ }
if (query->wait_comeback && !query->retry) {
eloop_cancel_timeout(gas_query_rx_comeback_timeout,
gas, query);
@@ -260,7 +274,7 @@ static void gas_query_tx_status(struct wpa_supplicant *wpa_s,
}
-static int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
+int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
{
if (wpa_s->current_ssid == NULL ||
wpa_s->wpa_state < WPA_4WAY_HANDSHAKE ||
@@ -280,8 +294,9 @@ static int gas_query_tx(struct gas_query *gas, struct gas_query_pending *query,
};
wpa_printf(MSG_DEBUG, "GAS: Send action frame to " MACSTR " len=%u "
- "freq=%d prot=%d", MAC2STR(query->addr),
- (unsigned int) wpabuf_len(req), query->freq, prot);
+ "freq=%d prot=%d using src addr " MACSTR,
+ MAC2STR(query->addr), (unsigned int) wpabuf_len(req),
+ query->freq, prot, MAC2STR(query->sa));
if (prot) {
u8 *categ = wpabuf_mhead_u8(req);
*categ = WLAN_ACTION_PROTECTED_DUAL;
@@ -290,17 +305,20 @@ static int gas_query_tx(struct gas_query *gas, struct gas_query_pending *query,
if (gas->wpa_s->max_remain_on_chan &&
wait_time > gas->wpa_s->max_remain_on_chan)
wait_time = gas->wpa_s->max_remain_on_chan;
- if (!gas->wpa_s->conf->gas_address3 ||
- (gas->wpa_s->current_ssid &&
- gas->wpa_s->wpa_state >= WPA_ASSOCIATED &&
- os_memcmp(query->addr, gas->wpa_s->bssid, ETH_ALEN) == 0))
+ if (!query->wildcard_bssid &&
+ (!gas->wpa_s->conf->gas_address3 ||
+ (gas->wpa_s->current_ssid &&
+ gas->wpa_s->wpa_state >= WPA_ASSOCIATED &&
+ os_memcmp(query->addr, gas->wpa_s->bssid, ETH_ALEN) == 0)))
bssid = query->addr;
else
bssid = wildcard_bssid;
+
res = offchannel_send_action(gas->wpa_s, query->freq, query->addr,
- gas->wpa_s->own_addr, bssid,
- wpabuf_head(req), wpabuf_len(req),
- wait_time, gas_query_tx_status, 0);
+ query->sa, bssid, wpabuf_head(req),
+ wpabuf_len(req), wait_time,
+ gas_query_tx_status, 0);
+
if (res == 0)
query->offchannel_tx_started = 1;
return res;
@@ -409,6 +427,7 @@ static void gas_query_rx_initial(struct gas_query *gas,
}
if (comeback_delay) {
+ eloop_cancel_timeout(gas_query_timeout, gas, query);
query->wait_comeback = 1;
gas_query_tx_comeback_req_delay(gas, query, comeback_delay);
return;
@@ -726,6 +745,58 @@ static int gas_query_new_dialog_token(struct gas_query *gas, const u8 *dst)
}
+static int gas_query_set_sa(struct gas_query *gas,
+ struct gas_query_pending *query)
+{
+ struct wpa_supplicant *wpa_s = gas->wpa_s;
+ struct os_reltime now;
+
+ if (!wpa_s->conf->gas_rand_mac_addr ||
+ !(wpa_s->current_bss ?
+ (wpa_s->drv_flags &
+ WPA_DRIVER_FLAGS_MGMT_TX_RANDOM_TA_CONNECTED) :
+ (wpa_s->drv_flags & WPA_DRIVER_FLAGS_MGMT_TX_RANDOM_TA))) {
+ /* Use own MAC address as the transmitter address */
+ os_memcpy(query->sa, wpa_s->own_addr, ETH_ALEN);
+ return 0;
+ }
+
+ os_get_reltime(&now);
+
+ if (wpa_s->conf->gas_rand_mac_addr == gas->last_rand_sa_type &&
+ gas->last_mac_addr_rand.sec != 0 &&
+ !os_reltime_expired(&now, &gas->last_mac_addr_rand,
+ wpa_s->conf->gas_rand_addr_lifetime)) {
+ wpa_printf(MSG_DEBUG,
+ "GAS: Use the previously selected random transmitter address "
+ MACSTR, MAC2STR(gas->rand_addr));
+ os_memcpy(query->sa, gas->rand_addr, ETH_ALEN);
+ return 0;
+ }
+
+ if (wpa_s->conf->gas_rand_mac_addr == 1 &&
+ random_mac_addr(gas->rand_addr) < 0) {
+ wpa_printf(MSG_ERROR, "GAS: Failed to get random address");
+ return -1;
+ }
+
+ if (wpa_s->conf->gas_rand_mac_addr == 2 &&
+ random_mac_addr_keep_oui(gas->rand_addr) < 0) {
+ wpa_printf(MSG_ERROR,
+ "GAS: Failed to get random address with same OUI");
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG, "GAS: Use a new random transmitter address "
+ MACSTR, MAC2STR(gas->rand_addr));
+ os_memcpy(query->sa, gas->rand_addr, ETH_ALEN);
+ os_get_reltime(&gas->last_mac_addr_rand);
+ gas->last_rand_sa_type = wpa_s->conf->gas_rand_mac_addr;
+
+ return 0;
+}
+
+
/**
* gas_query_req - Request a GAS query
* @gas: GAS query data from gas_query_init()
@@ -738,7 +809,7 @@ static int gas_query_new_dialog_token(struct gas_query *gas, const u8 *dst)
* Returns: dialog token (>= 0) on success or -1 on failure
*/
int gas_query_req(struct gas_query *gas, const u8 *dst, int freq,
- struct wpabuf *req,
+ int wildcard_bssid, struct wpabuf *req,
void (*cb)(void *ctx, const u8 *dst, u8 dialog_token,
enum gas_query_result result,
const struct wpabuf *adv_proto,
@@ -760,8 +831,13 @@ int gas_query_req(struct gas_query *gas, const u8 *dst, int freq,
return -1;
query->gas = gas;
+ if (gas_query_set_sa(gas, query)) {
+ os_free(query);
+ return -1;
+ }
os_memcpy(query->addr, dst, ETH_ALEN);
query->dialog_token = dialog_token;
+ query->wildcard_bssid = !!wildcard_bssid;
query->freq = freq;
query->cb = cb;
query->ctx = ctx;
@@ -783,3 +859,27 @@ int gas_query_req(struct gas_query *gas, const u8 *dst, int freq,
return dialog_token;
}
+
+
+int gas_query_stop(struct gas_query *gas, u8 dialog_token)
+{
+ struct gas_query_pending *query;
+
+ dl_list_for_each(query, &gas->pending, struct gas_query_pending, list) {
+ if (query->dialog_token == dialog_token) {
+ if (!gas->work) {
+ /* The pending radio work has not yet been
+ * started, but the pending entry has a
+ * reference to the soon to be freed query.
+ * Need to remove that radio work now to avoid
+ * leaving behind a reference to freed memory.
+ */
+ radio_remove_pending_work(gas->wpa_s, query);
+ }
+ gas_query_done(gas, query, GAS_QUERY_STOPPED);
+ return 0;
+ }
+ }
+
+ return -1;
+}
diff --git a/freebsd/contrib/wpa/wpa_supplicant/gas_query.h b/freebsd/contrib/wpa/wpa_supplicant/gas_query.h
index ef82097e..d2b45544 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/gas_query.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/gas_query.h
@@ -19,6 +19,7 @@ void gas_query_deinit(struct gas_query *gas);
int gas_query_rx(struct gas_query *gas, const u8 *da, const u8 *sa,
const u8 *bssid, u8 categ, const u8 *data, size_t len,
int freq);
+int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr);
/**
* enum gas_query_result - GAS query result
@@ -29,16 +30,18 @@ enum gas_query_result {
GAS_QUERY_TIMEOUT,
GAS_QUERY_PEER_ERROR,
GAS_QUERY_INTERNAL_ERROR,
+ GAS_QUERY_STOPPED,
GAS_QUERY_DELETED_AT_DEINIT
};
int gas_query_req(struct gas_query *gas, const u8 *dst, int freq,
- struct wpabuf *req,
+ int wildcard_bssid, struct wpabuf *req,
void (*cb)(void *ctx, const u8 *dst, u8 dialog_token,
enum gas_query_result result,
const struct wpabuf *adv_proto,
const struct wpabuf *resp, u16 status_code),
void *ctx);
+int gas_query_stop(struct gas_query *gas, u8 dialog_token);
#else /* CONFIG_GAS */
diff --git a/freebsd/contrib/wpa/wpa_supplicant/hs20_supplicant.c b/freebsd/contrib/wpa/wpa_supplicant/hs20_supplicant.c
index 44be415a..eb085c0d 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/hs20_supplicant.c
+++ b/freebsd/contrib/wpa/wpa_supplicant/hs20_supplicant.c
@@ -51,9 +51,12 @@ struct osu_provider {
u8 bssid[ETH_ALEN];
u8 osu_ssid[SSID_MAX_LEN];
u8 osu_ssid_len;
+ u8 osu_ssid2[SSID_MAX_LEN];
+ u8 osu_ssid2_len;
char server_uri[256];
u32 osu_methods; /* bit 0 = OMA-DM, bit 1 = SOAP-XML SPP */
char osu_nai[256];
+ char osu_nai2[256];
struct osu_lang_string friendly_name[OSU_MAX_ITEMS];
size_t friendly_name_count;
struct osu_lang_string serv_desc[OSU_MAX_ITEMS];
@@ -94,8 +97,7 @@ void hs20_configure_frame_filters(struct wpa_supplicant *wpa_s)
return;
}
- /* Check if Proxy ARP is enabled (2nd byte in the IE) */
- if (ext_capa[3] & BIT(4))
+ if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_PROXY_ARP))
filter |= WPA_DATA_FRAME_FILTER_FLAG_ARP |
WPA_DATA_FRAME_FILTER_FLAG_NA;
@@ -103,15 +105,22 @@ void hs20_configure_frame_filters(struct wpa_supplicant *wpa_s)
}
-void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id)
+void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id, int ap_release)
{
+ int release;
u8 conf;
+ release = (HS20_VERSION >> 4) + 1;
+ if (ap_release > 0 && release > ap_release)
+ release = ap_release;
+ if (release < 2)
+ pps_mo_id = -1;
+
wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
wpabuf_put_u8(buf, pps_mo_id >= 0 ? 7 : 5);
wpabuf_put_be24(buf, OUI_WFA);
wpabuf_put_u8(buf, HS20_INDICATION_OUI_TYPE);
- conf = HS20_VERSION;
+ conf = (release - 1) << 4;
if (pps_mo_id >= 0)
conf |= HS20_PPS_MO_ID_PRESENT;
wpabuf_put_u8(buf, conf);
@@ -120,6 +129,37 @@ void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id)
}
+void wpas_hs20_add_roam_cons_sel(struct wpabuf *buf,
+ const struct wpa_ssid *ssid)
+{
+ if (!ssid->roaming_consortium_selection ||
+ !ssid->roaming_consortium_selection_len)
+ return;
+
+ wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
+ wpabuf_put_u8(buf, 4 + ssid->roaming_consortium_selection_len);
+ wpabuf_put_be24(buf, OUI_WFA);
+ wpabuf_put_u8(buf, HS20_ROAMING_CONS_SEL_OUI_TYPE);
+ wpabuf_put_data(buf, ssid->roaming_consortium_selection,
+ ssid->roaming_consortium_selection_len);
+}
+
+
+int get_hs20_version(struct wpa_bss *bss)
+{
+ const u8 *ie;
+
+ if (!bss)
+ return 0;
+
+ ie = wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE);
+ if (!ie || ie[1] < 5)
+ return 0;
+
+ return ((ie[6] >> 4) & 0x0f) + 1;
+}
+
+
int is_hs20_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
struct wpa_bss *bss)
{
@@ -250,7 +290,7 @@ int hs20_anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, u32 stypes,
if (buf == NULL)
return -1;
- res = gas_query_req(wpa_s->gas, dst, freq, buf, anqp_resp_cb, wpa_s);
+ res = gas_query_req(wpa_s->gas, dst, freq, 0, buf, anqp_resp_cb, wpa_s);
if (res < 0) {
wpa_printf(MSG_DEBUG, "ANQP: Failed to send Query Request");
wpabuf_free(buf);
@@ -393,7 +433,7 @@ static void hs20_set_osu_access_permission(const char *osu_dir,
return;
}
- if (chown(fname, statbuf.st_uid, statbuf.st_gid) < 0) {
+ if (lchown(fname, statbuf.st_uid, statbuf.st_gid) < 0) {
wpa_printf(MSG_WARNING, "Cannot change the ownership for %s",
fname);
}
@@ -431,10 +471,9 @@ static int hs20_process_icon_binary_file(struct wpa_supplicant *wpa_s,
dl_list_for_each(icon, &wpa_s->icon_head, struct icon_entry, list) {
if (icon->dialog_token == dialog_token && !icon->image &&
os_memcmp(icon->bssid, sa, ETH_ALEN) == 0) {
- icon->image = os_malloc(slen);
+ icon->image = os_memdup(pos, slen);
if (!icon->image)
return -1;
- os_memcpy(icon->image, pos, slen);
icon->image_len = slen;
hs20_remove_duplicate_icons(wpa_s, icon);
wpa_msg(wpa_s, MSG_INFO,
@@ -648,6 +687,25 @@ void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s,
wpa_s, NULL);
}
break;
+ case HS20_STYPE_OPERATOR_ICON_METADATA:
+ wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
+ " Operator Icon Metadata", MAC2STR(sa));
+ wpa_hexdump(MSG_DEBUG, "Operator Icon Metadata", pos, slen);
+ if (anqp) {
+ wpabuf_free(anqp->hs20_operator_icon_metadata);
+ anqp->hs20_operator_icon_metadata =
+ wpabuf_alloc_copy(pos, slen);
+ }
+ break;
+ case HS20_STYPE_OSU_PROVIDERS_NAI_LIST:
+ wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
+ " OSU Providers NAI List", MAC2STR(sa));
+ if (anqp) {
+ wpabuf_free(anqp->hs20_osu_providers_nai_list);
+ anqp->hs20_osu_providers_nai_list =
+ wpabuf_alloc_copy(pos, slen);
+ }
+ break;
default:
wpa_printf(MSG_DEBUG, "HS20: Unsupported subtype %u", subtype);
break;
@@ -727,8 +785,15 @@ static void hs20_osu_fetch_done(struct wpa_supplicant *wpa_s)
wpa_ssid_txt(osu->osu_ssid,
osu->osu_ssid_len));
}
+ if (osu->osu_ssid2_len) {
+ fprintf(f, "osu_ssid2=%s\n",
+ wpa_ssid_txt(osu->osu_ssid2,
+ osu->osu_ssid2_len));
+ }
if (osu->osu_nai[0])
fprintf(f, "osu_nai=%s\n", osu->osu_nai);
+ if (osu->osu_nai2[0])
+ fprintf(f, "osu_nai2=%s\n", osu->osu_nai2);
for (j = 0; j < osu->friendly_name_count; j++) {
fprintf(f, "friendly_name=%s:%s\n",
osu->friendly_name[j].lang,
@@ -792,6 +857,7 @@ void hs20_next_osu_icon(struct wpa_supplicant *wpa_s)
static void hs20_osu_add_prov(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
const u8 *osu_ssid, u8 osu_ssid_len,
+ const u8 *osu_ssid2, u8 osu_ssid2_len,
const u8 *pos, size_t len)
{
struct osu_provider *prov;
@@ -813,6 +879,9 @@ static void hs20_osu_add_prov(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
os_memcpy(prov->bssid, bss->bssid, ETH_ALEN);
os_memcpy(prov->osu_ssid, osu_ssid, osu_ssid_len);
prov->osu_ssid_len = osu_ssid_len;
+ if (osu_ssid2)
+ os_memcpy(prov->osu_ssid2, osu_ssid2, osu_ssid2_len);
+ prov->osu_ssid2_len = osu_ssid2_len;
/* OSU Friendly Name Length */
if (end - pos < 2) {
@@ -994,18 +1063,30 @@ void hs20_osu_icon_fetch(struct wpa_supplicant *wpa_s)
struct wpabuf *prov_anqp;
const u8 *pos, *end;
u16 len;
- const u8 *osu_ssid;
- u8 osu_ssid_len;
+ const u8 *osu_ssid, *osu_ssid2;
+ u8 osu_ssid_len, osu_ssid2_len;
u8 num_providers;
hs20_free_osu_prov(wpa_s);
dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
+ struct wpa_ie_data data;
+ const u8 *ie;
+
if (bss->anqp == NULL)
continue;
prov_anqp = bss->anqp->hs20_osu_providers_list;
if (prov_anqp == NULL)
continue;
+ ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
+ if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &data) == 0 &&
+ (data.key_mgmt & WPA_KEY_MGMT_OSEN)) {
+ osu_ssid2 = bss->ssid;
+ osu_ssid2_len = bss->ssid_len;
+ } else {
+ osu_ssid2 = NULL;
+ osu_ssid2_len = 0;
+ }
wpa_printf(MSG_DEBUG, "HS 2.0: Parsing OSU Providers list from "
MACSTR, MAC2STR(bss->bssid));
wpa_hexdump_buf(MSG_DEBUG, "HS 2.0: OSU Providers list",
@@ -1047,7 +1128,8 @@ void hs20_osu_icon_fetch(struct wpa_supplicant *wpa_s)
if (len > (unsigned int) (end - pos))
break;
hs20_osu_add_prov(wpa_s, bss, osu_ssid,
- osu_ssid_len, pos, len);
+ osu_ssid_len, osu_ssid2,
+ osu_ssid2_len, pos, len);
pos += len;
}
@@ -1056,6 +1138,35 @@ void hs20_osu_icon_fetch(struct wpa_supplicant *wpa_s)
"extra data after OSU Providers",
(int) (end - pos));
}
+
+ prov_anqp = bss->anqp->hs20_osu_providers_nai_list;
+ if (!prov_anqp)
+ continue;
+ wpa_printf(MSG_DEBUG,
+ "HS 2.0: Parsing OSU Providers NAI List from "
+ MACSTR, MAC2STR(bss->bssid));
+ wpa_hexdump_buf(MSG_DEBUG, "HS 2.0: OSU Providers NAI List",
+ prov_anqp);
+ pos = wpabuf_head(prov_anqp);
+ end = pos + wpabuf_len(prov_anqp);
+ num_providers = 0;
+ while (end - pos > 0) {
+ len = *pos++;
+ if (end - pos < len) {
+ wpa_printf(MSG_DEBUG,
+ "HS 2.0: Not enough room for OSU_NAI");
+ break;
+ }
+ if (num_providers >= wpa_s->osu_prov_count) {
+ wpa_printf(MSG_DEBUG,
+ "HS 2.0: Ignore unexpected OSU Provider NAI List entries");
+ break;
+ }
+ os_memcpy(wpa_s->osu_prov[num_providers].osu_nai2,
+ pos, len);
+ pos += len;
+ num_providers++;
+ }
}
wpa_s->fetch_osu_icon_in_progress = 1;
@@ -1209,6 +1320,18 @@ void hs20_rx_deauth_imminent_notice(struct wpa_supplicant *wpa_s, u8 code,
}
+void hs20_rx_t_c_acceptance(struct wpa_supplicant *wpa_s, const char *url)
+{
+ if (!wpa_sm_pmf_enabled(wpa_s->wpa)) {
+ wpa_printf(MSG_DEBUG,
+ "HS 2.0: Ignore Terms and Conditions Acceptance since PMF was not enabled");
+ return;
+ }
+
+ wpa_msg(wpa_s, MSG_INFO, HS20_T_C_ACCEPTANCE "%s", url);
+}
+
+
void hs20_init(struct wpa_supplicant *wpa_s)
{
dl_list_init(&wpa_s->icon_head);
diff --git a/freebsd/contrib/wpa/wpa_supplicant/hs20_supplicant.h b/freebsd/contrib/wpa/wpa_supplicant/hs20_supplicant.h
index 0dd559fd..e43414bc 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/hs20_supplicant.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/hs20_supplicant.h
@@ -9,7 +9,10 @@
#define HS20_SUPPLICANT_H
void hs20_configure_frame_filters(struct wpa_supplicant *wpa_s);
-void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id);
+void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id,
+ int ap_release);
+void wpas_hs20_add_roam_cons_sel(struct wpabuf *buf,
+ const struct wpa_ssid *ssid);
int hs20_anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, u32 stypes,
const u8 *payload, size_t payload_len, int inmem);
@@ -18,6 +21,7 @@ void hs20_put_anqp_req(u32 stypes, const u8 *payload, size_t payload_len,
void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s,
struct wpa_bss *bss, const u8 *sa,
const u8 *data, size_t slen, u8 dialog_token);
+int get_hs20_version(struct wpa_bss *bss);
int is_hs20_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
struct wpa_bss *bss);
int hs20_get_pps_mo_id(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
@@ -27,6 +31,7 @@ void hs20_rx_subscription_remediation(struct wpa_supplicant *wpa_s,
const char *url, u8 osu_method);
void hs20_rx_deauth_imminent_notice(struct wpa_supplicant *wpa_s, u8 code,
u16 reauth_delay, const char *url);
+void hs20_rx_t_c_acceptance(struct wpa_supplicant *wpa_s, const char *url);
void hs20_free_osu_prov(struct wpa_supplicant *wpa_s);
void hs20_next_osu_icon(struct wpa_supplicant *wpa_s);
diff --git a/freebsd/contrib/wpa/wpa_supplicant/interworking.c b/freebsd/contrib/wpa/wpa_supplicant/interworking.c
index 89f9a9be..44829a66 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/interworking.c
+++ b/freebsd/contrib/wpa/wpa_supplicant/interworking.c
@@ -108,10 +108,12 @@ static struct wpabuf * anqp_build_req(u16 info_ids[], size_t num_ids,
if (buf == NULL)
return NULL;
- len_pos = gas_anqp_add_element(buf, ANQP_QUERY_LIST);
- for (i = 0; i < num_ids; i++)
- wpabuf_put_le16(buf, info_ids[i]);
- gas_anqp_set_element_len(buf, len_pos);
+ if (num_ids > 0) {
+ len_pos = gas_anqp_add_element(buf, ANQP_QUERY_LIST);
+ for (i = 0; i < num_ids; i++)
+ wpabuf_put_le16(buf, info_ids[i]);
+ gas_anqp_set_element_len(buf, len_pos);
+ }
if (extra)
wpabuf_put_buf(buf, extra);
@@ -148,6 +150,8 @@ static int cred_with_roaming_consortium(struct wpa_supplicant *wpa_s)
return 1;
if (cred->required_roaming_consortium_len)
return 1;
+ if (cred->num_roaming_consortiums)
+ return 1;
}
return 0;
}
@@ -301,8 +305,10 @@ static int interworking_anqp_send_req(struct wpa_supplicant *wpa_s,
wpabuf_put_u8(extra, HS20_STYPE_CONNECTION_CAPABILITY);
if (all)
wpabuf_put_u8(extra, HS20_STYPE_OPERATING_CLASS);
- if (all)
+ if (all) {
wpabuf_put_u8(extra, HS20_STYPE_OSU_PROVIDERS_LIST);
+ wpabuf_put_u8(extra, HS20_STYPE_OSU_PROVIDERS_NAI_LIST);
+ }
gas_anqp_set_element_len(extra, len_pos);
}
#endif /* CONFIG_HS20 */
@@ -312,7 +318,7 @@ static int interworking_anqp_send_req(struct wpa_supplicant *wpa_s,
if (buf == NULL)
return -1;
- res = gas_query_req(wpa_s->gas, bss->bssid, bss->freq, buf,
+ res = gas_query_req(wpa_s->gas, bss->bssid, bss->freq, 0, buf,
interworking_anqp_resp_cb, wpa_s);
if (res < 0) {
wpa_msg(wpa_s, MSG_DEBUG, "ANQP: Failed to send Query Request");
@@ -954,6 +960,7 @@ static int interworking_set_hs20_params(struct wpa_supplicant *wpa_s,
"WPA-EAP WPA-EAP-SHA256" : "WPA-EAP";
if (wpa_config_set(ssid, "key_mgmt", key_mgmt, 0) < 0 ||
wpa_config_set(ssid, "proto", "RSN", 0) < 0 ||
+ wpa_config_set(ssid, "ieee80211w", "1", 0) < 0 ||
wpa_config_set(ssid, "pairwise", "CCMP", 0) < 0)
return -1;
return 0;
@@ -1145,6 +1152,23 @@ static int roaming_consortium_match(const u8 *ie, const struct wpabuf *anqp,
}
+static int cred_roaming_consortiums_match(const u8 *ie,
+ const struct wpabuf *anqp,
+ const struct wpa_cred *cred)
+{
+ unsigned int i;
+
+ for (i = 0; i < cred->num_roaming_consortiums; i++) {
+ if (roaming_consortium_match(ie, anqp,
+ cred->roaming_consortiums[i],
+ cred->roaming_consortiums_len[i]))
+ return 1;
+ }
+
+ return 0;
+}
+
+
static int cred_no_required_oi_match(struct wpa_cred *cred, struct wpa_bss *bss)
{
const u8 *ie;
@@ -1349,27 +1373,28 @@ static struct wpa_cred * interworking_credentials_available_roaming_consortium(
{
struct wpa_cred *cred, *selected = NULL;
const u8 *ie;
+ const struct wpabuf *anqp;
int is_excluded = 0;
ie = wpa_bss_get_ie(bss, WLAN_EID_ROAMING_CONSORTIUM);
+ anqp = bss->anqp ? bss->anqp->roaming_consortium : NULL;
- if (ie == NULL &&
- (bss->anqp == NULL || bss->anqp->roaming_consortium == NULL))
+ if (!ie && !anqp)
return NULL;
if (wpa_s->conf->cred == NULL)
return NULL;
for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
- if (cred->roaming_consortium_len == 0)
+ if (cred->roaming_consortium_len == 0 &&
+ cred->num_roaming_consortiums == 0)
continue;
- if (!roaming_consortium_match(ie,
- bss->anqp ?
- bss->anqp->roaming_consortium :
- NULL,
- cred->roaming_consortium,
- cred->roaming_consortium_len))
+ if ((cred->roaming_consortium_len == 0 ||
+ !roaming_consortium_match(ie, anqp,
+ cred->roaming_consortium,
+ cred->roaming_consortium_len)) &&
+ !cred_roaming_consortiums_match(ie, anqp, cred))
continue;
if (cred_no_required_oi_match(cred, bss))
@@ -1535,6 +1560,9 @@ static int interworking_connect_roaming_consortium(
struct wpa_bss *bss, int only_add)
{
struct wpa_ssid *ssid;
+ const u8 *ie;
+ const struct wpabuf *anqp;
+ unsigned int i;
wpa_msg(wpa_s, MSG_DEBUG, "Interworking: Connect with " MACSTR
" based on roaming consortium match", MAC2STR(bss->bssid));
@@ -1564,6 +1592,26 @@ static int interworking_connect_roaming_consortium(
if (interworking_set_hs20_params(wpa_s, ssid) < 0)
goto fail;
+ ie = wpa_bss_get_ie(bss, WLAN_EID_ROAMING_CONSORTIUM);
+ anqp = bss->anqp ? bss->anqp->roaming_consortium : NULL;
+ for (i = 0; (ie || anqp) && i < cred->num_roaming_consortiums; i++) {
+ if (!roaming_consortium_match(
+ ie, anqp, cred->roaming_consortiums[i],
+ cred->roaming_consortiums_len[i]))
+ continue;
+
+ ssid->roaming_consortium_selection =
+ os_malloc(cred->roaming_consortiums_len[i]);
+ if (!ssid->roaming_consortium_selection)
+ goto fail;
+ os_memcpy(ssid->roaming_consortium_selection,
+ cred->roaming_consortiums[i],
+ cred->roaming_consortiums_len[i]);
+ ssid->roaming_consortium_selection_len =
+ cred->roaming_consortiums_len[i];
+ break;
+ }
+
if (cred->eap_method == NULL) {
wpa_msg(wpa_s, MSG_DEBUG,
"Interworking: No EAP method set for credential using roaming consortium");
@@ -1771,9 +1819,10 @@ int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
switch (eap->method) {
case EAP_TYPE_TTLS:
if (eap->inner_method) {
- os_snprintf(buf, sizeof(buf), "\"autheap=%s\"",
- eap_get_name(EAP_VENDOR_IETF,
- eap->inner_method));
+ name = eap_get_name(EAP_VENDOR_IETF, eap->inner_method);
+ if (!name)
+ goto fail;
+ os_snprintf(buf, sizeof(buf), "\"autheap=%s\"", name);
if (wpa_config_set(ssid, "phase2", buf, 0) < 0)
goto fail;
break;
@@ -1896,7 +1945,7 @@ static struct wpa_cred * interworking_credentials_available_3gpp(
size_t len;
wpa_msg(wpa_s, MSG_DEBUG,
"Interworking: IMSI not available - try to read again through eap_proxy");
- wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol,
+ wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
wpa_s->imsi,
&len);
if (wpa_s->mnc_len > 0) {
@@ -2532,7 +2581,8 @@ static void interworking_select_network(struct wpa_supplicant *wpa_s)
wpa_msg(wpa_s, MSG_INFO, INTERWORKING_SELECTED MACSTR,
MAC2STR(selected->bssid));
interworking_connect(wpa_s, selected, 0);
- }
+ } else if (wpa_s->wpa_state == WPA_SCANNING)
+ wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
}
@@ -2578,7 +2628,6 @@ static void interworking_next_anqp_fetch(struct wpa_supplicant *wpa_s)
{
struct wpa_bss *bss;
int found = 0;
- const u8 *ie;
wpa_printf(MSG_DEBUG, "Interworking: next_anqp_fetch - "
"fetch_anqp_in_progress=%d fetch_osu_icon_in_progress=%d",
@@ -2601,8 +2650,7 @@ static void interworking_next_anqp_fetch(struct wpa_supplicant *wpa_s)
dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
if (!(bss->caps & IEEE80211_CAP_ESS))
continue;
- ie = wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB);
- if (ie == NULL || ie[1] < 4 || !(ie[5] & 0x80))
+ if (!wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_INTERWORKING))
continue; /* AP does not support Interworking */
if (disallowed_bssid(wpa_s, bss->bssid) ||
disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len))
@@ -2695,7 +2743,7 @@ void interworking_stop_fetch_anqp(struct wpa_supplicant *wpa_s)
int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst,
u16 info_ids[], size_t num_ids, u32 subtypes,
- int get_cell_pref)
+ u32 mbo_subtypes)
{
struct wpabuf *buf;
struct wpabuf *extra_buf = NULL;
@@ -2729,13 +2777,14 @@ int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst,
#endif /* CONFIG_HS20 */
#ifdef CONFIG_MBO
- if (get_cell_pref) {
+ if (mbo_subtypes) {
struct wpabuf *mbo;
- mbo = mbo_build_anqp_buf(wpa_s, bss);
+ mbo = mbo_build_anqp_buf(wpa_s, bss, mbo_subtypes);
if (mbo) {
if (wpabuf_resize(&extra_buf, wpabuf_len(mbo))) {
wpabuf_free(extra_buf);
+ wpabuf_free(mbo);
return -1;
}
wpabuf_put_buf(extra_buf, mbo);
@@ -2749,7 +2798,7 @@ int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst,
if (buf == NULL)
return -1;
- res = gas_query_req(wpa_s->gas, dst, freq, buf, anqp_resp_cb, wpa_s);
+ res = gas_query_req(wpa_s->gas, dst, freq, 0, buf, anqp_resp_cb, wpa_s);
if (res < 0) {
wpa_msg(wpa_s, MSG_DEBUG, "ANQP: Failed to send Query Request");
wpabuf_free(buf);
@@ -2798,6 +2847,31 @@ static void anqp_add_extra(struct wpa_supplicant *wpa_s,
}
+static void interworking_parse_venue_url(struct wpa_supplicant *wpa_s,
+ const u8 *data, size_t len)
+{
+ const u8 *pos = data, *end = data + len;
+ char url[255];
+
+ while (end - pos >= 2) {
+ u8 slen, num;
+
+ slen = *pos++;
+ if (slen < 1 || slen > end - pos) {
+ wpa_printf(MSG_DEBUG,
+ "ANQP: Truncated Venue URL Duple field");
+ return;
+ }
+
+ num = *pos++;
+ os_memcpy(url, pos, slen - 1);
+ url[slen - 1] = '\0';
+ wpa_msg(wpa_s, MSG_INFO, RX_VENUE_URL "%u %s", num, url);
+ pos += slen - 1;
+ }
+}
+
+
static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
struct wpa_bss *bss, const u8 *sa,
u16 info_id,
@@ -2806,9 +2880,7 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
{
const u8 *pos = data;
struct wpa_bss_anqp *anqp = NULL;
-#ifdef CONFIG_HS20
u8 type;
-#endif /* CONFIG_HS20 */
if (bss)
anqp = bss->anqp;
@@ -2894,12 +2966,35 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
anqp->domain_name = wpabuf_alloc_copy(pos, slen);
}
break;
+#ifdef CONFIG_FILS
+ case ANQP_FILS_REALM_INFO:
+ wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
+ " FILS Realm Information", MAC2STR(sa));
+ wpa_hexdump_ascii(MSG_MSGDUMP, "ANQP: FILS Realm Information",
+ pos, slen);
+ if (anqp) {
+ wpabuf_free(anqp->fils_realm_info);
+ anqp->fils_realm_info = wpabuf_alloc_copy(pos, slen);
+ }
+ break;
+#endif /* CONFIG_FILS */
+ case ANQP_VENUE_URL:
+ wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR " Venue URL",
+ MAC2STR(sa));
+ anqp_add_extra(wpa_s, anqp, info_id, pos, slen);
+
+ if (!pmf_in_use(wpa_s, sa)) {
+ wpa_printf(MSG_DEBUG,
+ "ANQP: Ignore Venue URL since PMF was not enabled");
+ break;
+ }
+ interworking_parse_venue_url(wpa_s, pos, slen);
+ break;
case ANQP_VENDOR_SPECIFIC:
if (slen < 3)
return;
switch (WPA_GET_BE24(pos)) {
-#ifdef CONFIG_HS20
case OUI_WFA:
pos += 3;
slen -= 3;
@@ -2910,19 +3005,26 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
slen--;
switch (type) {
+#ifdef CONFIG_HS20
case HS20_ANQP_OUI_TYPE:
hs20_parse_rx_hs20_anqp_resp(wpa_s, bss, sa,
pos, slen,
dialog_token);
break;
+#endif /* CONFIG_HS20 */
+#ifdef CONFIG_MBO
+ case MBO_ANQP_OUI_TYPE:
+ mbo_parse_rx_anqp_resp(wpa_s, bss, sa,
+ pos, slen);
+ break;
+#endif /* CONFIG_MBO */
default:
wpa_msg(wpa_s, MSG_DEBUG,
- "HS20: Unsupported ANQP vendor type %u",
+ "ANQP: Unsupported ANQP vendor type %u",
type);
break;
}
break;
-#endif /* CONFIG_HS20 */
default:
wpa_msg(wpa_s, MSG_DEBUG,
"Interworking: Unsupported vendor-specific ANQP OUI %06x",
@@ -3135,7 +3237,7 @@ int gas_send_request(struct wpa_supplicant *wpa_s, const u8 *dst,
} else
wpabuf_put_le16(buf, 0);
- res = gas_query_req(wpa_s->gas, dst, freq, buf, gas_resp_cb, wpa_s);
+ res = gas_query_req(wpa_s->gas, dst, freq, 0, buf, gas_resp_cb, wpa_s);
if (res < 0) {
wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request");
wpabuf_free(buf);
diff --git a/freebsd/contrib/wpa/wpa_supplicant/interworking.h b/freebsd/contrib/wpa/wpa_supplicant/interworking.h
index 3d222926..37ee2e90 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/interworking.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/interworking.h
@@ -13,7 +13,7 @@ enum gas_query_result;
int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst,
u16 info_ids[], size_t num_ids, u32 subtypes,
- int get_cell_pref);
+ u32 mbo_subtypes);
void anqp_resp_cb(void *ctx, const u8 *dst, u8 dialog_token,
enum gas_query_result result,
const struct wpabuf *adv_proto,
diff --git a/freebsd/contrib/wpa/wpa_supplicant/main.c b/freebsd/contrib/wpa/wpa_supplicant/main.c
index 99c86920..0bd79a1e 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/main.c
+++ b/freebsd/contrib/wpa/wpa_supplicant/main.c
@@ -38,9 +38,9 @@ static void usage(void)
"s"
#endif /* CONFIG_DEBUG_SYSLOG */
"t"
-#ifdef CONFIG_DBUS
+#ifdef CONFIG_CTRL_IFACE_DBUS_NEW
"u"
-#endif /* CONFIG_DBUS */
+#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
"vW] [-P<pid file>] "
"[-g<global ctrl>] \\\n"
" [-G<group>] \\\n"
@@ -108,9 +108,9 @@ static void usage(void)
" -T = record to Linux tracing in addition to logging\n"
" (records all messages regardless of debug verbosity)\n"
#endif /* CONFIG_DEBUG_LINUX_TRACING */
-#ifdef CONFIG_DBUS
+#ifdef CONFIG_CTRL_IFACE_DBUS_NEW
" -u = enable DBus control interface\n"
-#endif /* CONFIG_DBUS */
+#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
" -v = show version\n"
" -W = wait for a control interface monitor before starting\n");
@@ -235,6 +235,11 @@ int main(int argc, char *argv[])
wpa_supplicant_fd_workaround(1);
+#ifdef CONFIG_DRIVER_NDIS
+ void driver_ndis_init_ops(void);
+ driver_ndis_init_ops();
+#endif /* CONFIG_DRIVER_NDIS */
+
for (;;) {
c = getopt(argc, argv,
"b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuvW");
@@ -331,11 +336,11 @@ int main(int argc, char *argv[])
case 't':
params.wpa_debug_timestamp++;
break;
-#ifdef CONFIG_DBUS
+#ifdef CONFIG_CTRL_IFACE_DBUS_NEW
case 'u':
params.dbus_ctrl_interface = 1;
break;
-#endif /* CONFIG_DBUS */
+#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
case 'v':
printf("%s\n", wpa_supplicant_version);
exitcode = 0;
diff --git a/freebsd/contrib/wpa/wpa_supplicant/notify.c b/freebsd/contrib/wpa/wpa_supplicant/notify.c
index 020a9a7b..c1fb8aed 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/notify.c
+++ b/freebsd/contrib/wpa/wpa_supplicant/notify.c
@@ -17,7 +17,6 @@
#include "wps_supplicant.h"
#include "binder/binder.h"
#include "dbus/dbus_common.h"
-#include "dbus/dbus_old.h"
#include "dbus/dbus_new.h"
#include "rsn_supp/wpa.h"
#include "fst/fst.h"
@@ -29,13 +28,13 @@
int wpas_notify_supplicant_initialized(struct wpa_global *global)
{
-#ifdef CONFIG_DBUS
+#ifdef CONFIG_CTRL_IFACE_DBUS_NEW
if (global->params.dbus_ctrl_interface) {
global->dbus = wpas_dbus_init(global);
if (global->dbus == NULL)
return -1;
}
-#endif /* CONFIG_DBUS */
+#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
#ifdef CONFIG_BINDER
global->binder = wpas_binder_init(global);
@@ -49,10 +48,10 @@ int wpas_notify_supplicant_initialized(struct wpa_global *global)
void wpas_notify_supplicant_deinitialized(struct wpa_global *global)
{
-#ifdef CONFIG_DBUS
+#ifdef CONFIG_CTRL_IFACE_DBUS_NEW
if (global->dbus)
wpas_dbus_deinit(global->dbus);
-#endif /* CONFIG_DBUS */
+#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
#ifdef CONFIG_BINDER
if (global->binder)
@@ -66,9 +65,6 @@ int wpas_notify_iface_added(struct wpa_supplicant *wpa_s)
if (wpa_s->p2p_mgmt)
return 0;
- if (wpas_dbus_register_iface(wpa_s))
- return -1;
-
if (wpas_dbus_register_interface(wpa_s))
return -1;
@@ -81,9 +77,6 @@ void wpas_notify_iface_removed(struct wpa_supplicant *wpa_s)
if (wpa_s->p2p_mgmt)
return;
- /* unregister interface in old DBus ctrl iface */
- wpas_dbus_unregister_iface(wpa_s);
-
/* unregister interface in new DBus ctrl iface */
wpas_dbus_unregister_interface(wpa_s);
}
@@ -96,10 +89,6 @@ void wpas_notify_state_changed(struct wpa_supplicant *wpa_s,
if (wpa_s->p2p_mgmt)
return;
- /* notify the old DBus API */
- wpa_supplicant_dbus_notify_state_change(wpa_s, new_state,
- old_state);
-
/* notify the new DBus API */
wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATE);
@@ -142,6 +131,15 @@ void wpas_notify_disconnect_reason(struct wpa_supplicant *wpa_s)
}
+void wpas_notify_auth_status_code(struct wpa_supplicant *wpa_s)
+{
+ if (wpa_s->p2p_mgmt)
+ return;
+
+ wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_AUTH_STATUS_CODE);
+}
+
+
void wpas_notify_assoc_status_code(struct wpa_supplicant *wpa_s)
{
if (wpa_s->p2p_mgmt)
@@ -151,6 +149,42 @@ void wpas_notify_assoc_status_code(struct wpa_supplicant *wpa_s)
}
+void wpas_notify_roam_time(struct wpa_supplicant *wpa_s)
+{
+ if (wpa_s->p2p_mgmt)
+ return;
+
+ wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_ROAM_TIME);
+}
+
+
+void wpas_notify_roam_complete(struct wpa_supplicant *wpa_s)
+{
+ if (wpa_s->p2p_mgmt)
+ return;
+
+ wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_ROAM_COMPLETE);
+}
+
+
+void wpas_notify_session_length(struct wpa_supplicant *wpa_s)
+{
+ if (wpa_s->p2p_mgmt)
+ return;
+
+ wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_SESSION_LENGTH);
+}
+
+
+void wpas_notify_bss_tm_status(struct wpa_supplicant *wpa_s)
+{
+ if (wpa_s->p2p_mgmt)
+ return;
+
+ wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSS_TM_STATUS);
+}
+
+
void wpas_notify_network_changed(struct wpa_supplicant *wpa_s)
{
if (wpa_s->p2p_mgmt)
@@ -224,9 +258,6 @@ void wpas_notify_scanning(struct wpa_supplicant *wpa_s)
if (wpa_s->p2p_mgmt)
return;
- /* notify the old DBus API */
- wpa_supplicant_dbus_notify_scanning(wpa_s);
-
/* notify the new DBus API */
wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_SCANNING);
}
@@ -246,9 +277,6 @@ void wpas_notify_scan_results(struct wpa_supplicant *wpa_s)
if (wpa_s->p2p_mgmt)
return;
- /* notify the old DBus API */
- wpa_supplicant_dbus_notify_scan_results(wpa_s);
-
wpas_wps_notify_scan_results(wpa_s);
}
@@ -260,8 +288,6 @@ void wpas_notify_wps_credential(struct wpa_supplicant *wpa_s,
return;
#ifdef CONFIG_WPS
- /* notify the old DBus API */
- wpa_supplicant_dbus_notify_wps_cred(wpa_s, cred);
/* notify the new DBus API */
wpas_dbus_signal_wps_cred(wpa_s, cred);
#endif /* CONFIG_WPS */
@@ -671,12 +697,12 @@ void wpas_notify_p2p_provision_discovery(struct wpa_supplicant *wpa_s,
void wpas_notify_p2p_group_started(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid, int persistent,
- int client)
+ int client, const u8 *ip)
{
/* Notify a group has been started */
wpas_dbus_register_p2p_group(wpa_s, ssid);
- wpas_dbus_signal_p2p_group_started(wpa_s, client, persistent);
+ wpas_dbus_signal_p2p_group_started(wpa_s, client, persistent, ip);
}
@@ -722,6 +748,9 @@ static void wpas_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s,
wpas_dbus_signal_p2p_peer_joined(wpa_s, p2p_dev_addr);
#endif /* CONFIG_P2P */
+ /* Register the station */
+ wpas_dbus_register_sta(wpa_s, sta);
+
/* Notify listeners a new station has been authorized */
wpas_dbus_signal_sta_authorized(wpa_s, sta);
}
@@ -742,6 +771,9 @@ static void wpas_notify_ap_sta_deauthorized(struct wpa_supplicant *wpa_s,
/* Notify listeners a station has been deauthorized */
wpas_dbus_signal_sta_deauthorized(wpa_s, sta);
+
+ /* Unregister the station */
+ wpas_dbus_unregister_sta(wpa_s, sta);
}
@@ -789,9 +821,6 @@ void wpas_notify_certification(struct wpa_supplicant *wpa_s, int depth,
"depth=%d %s", depth, altsubject[i]);
}
- /* notify the old DBus API */
- wpa_supplicant_dbus_notify_certification(wpa_s, depth, subject,
- cert_hash, cert);
/* notify the new DBus API */
wpas_dbus_signal_certification(wpa_s, depth, subject, altsubject,
num_altsubject, cert_hash, cert);
@@ -818,6 +847,12 @@ void wpas_notify_eap_status(struct wpa_supplicant *wpa_s, const char *status,
}
+void wpas_notify_eap_error(struct wpa_supplicant *wpa_s, int error_code)
+{
+ wpa_msg(wpa_s, MSG_ERROR, WPA_EVENT_EAP_ERROR_CODE "%d", error_code);
+}
+
+
void wpas_notify_network_bssid_set_changed(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid)
{
@@ -852,3 +887,49 @@ void wpas_notify_network_type_changed(struct wpa_supplicant *wpa_s,
}
#endif /* CONFIG_P2P */
}
+
+
+#ifdef CONFIG_MESH
+
+void wpas_notify_mesh_group_started(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid)
+{
+ if (wpa_s->p2p_mgmt)
+ return;
+
+ wpas_dbus_signal_mesh_group_started(wpa_s, ssid);
+}
+
+
+void wpas_notify_mesh_group_removed(struct wpa_supplicant *wpa_s,
+ const u8 *meshid, u8 meshid_len,
+ int reason_code)
+{
+ if (wpa_s->p2p_mgmt)
+ return;
+
+ wpas_dbus_signal_mesh_group_removed(wpa_s, meshid, meshid_len,
+ reason_code);
+}
+
+
+void wpas_notify_mesh_peer_connected(struct wpa_supplicant *wpa_s,
+ const u8 *peer_addr)
+{
+ if (wpa_s->p2p_mgmt)
+ return;
+
+ wpas_dbus_signal_mesh_peer_connected(wpa_s, peer_addr);
+}
+
+
+void wpas_notify_mesh_peer_disconnected(struct wpa_supplicant *wpa_s,
+ const u8 *peer_addr, int reason_code)
+{
+ if (wpa_s->p2p_mgmt)
+ return;
+
+ wpas_dbus_signal_mesh_peer_disconnected(wpa_s, peer_addr, reason_code);
+}
+
+#endif /* CONFIG_MESH */
diff --git a/freebsd/contrib/wpa/wpa_supplicant/notify.h b/freebsd/contrib/wpa/wpa_supplicant/notify.h
index 8cce0f30..65f513ea 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/notify.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/notify.h
@@ -23,7 +23,12 @@ void wpas_notify_state_changed(struct wpa_supplicant *wpa_s,
enum wpa_states new_state,
enum wpa_states old_state);
void wpas_notify_disconnect_reason(struct wpa_supplicant *wpa_s);
+void wpas_notify_auth_status_code(struct wpa_supplicant *wpa_s);
void wpas_notify_assoc_status_code(struct wpa_supplicant *wpa_s);
+void wpas_notify_roam_time(struct wpa_supplicant *wpa_s);
+void wpas_notify_roam_complete(struct wpa_supplicant *wpa_s);
+void wpas_notify_session_length(struct wpa_supplicant *wpa_s);
+void wpas_notify_bss_tm_status(struct wpa_supplicant *wpa_s);
void wpas_notify_network_changed(struct wpa_supplicant *wpa_s);
void wpas_notify_ap_scan_changed(struct wpa_supplicant *wpa_s);
void wpas_notify_bssid_changed(struct wpa_supplicant *wpa_s);
@@ -114,7 +119,7 @@ void wpas_notify_p2p_provision_discovery(struct wpa_supplicant *wpa_s,
unsigned int generated_pin);
void wpas_notify_p2p_group_started(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid, int persistent,
- int client);
+ int client, const u8 *ip);
void wpas_notify_p2p_group_formation_failure(struct wpa_supplicant *wpa_s,
const char *reason);
void wpas_notify_persistent_group_added(struct wpa_supplicant *wpa_s,
@@ -134,6 +139,7 @@ void wpas_notify_preq(struct wpa_supplicant *wpa_s,
const u8 *ie, size_t ie_len, u32 ssi_signal);
void wpas_notify_eap_status(struct wpa_supplicant *wpa_s, const char *status,
const char *parameter);
+void wpas_notify_eap_error(struct wpa_supplicant *wpa_s, int error_code);
void wpas_notify_network_bssid_set_changed(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid);
void wpas_notify_network_type_changed(struct wpa_supplicant *wpa_s,
@@ -141,5 +147,14 @@ void wpas_notify_network_type_changed(struct wpa_supplicant *wpa_s,
void wpas_notify_p2p_invitation_received(struct wpa_supplicant *wpa_s,
const u8 *sa, const u8 *go_dev_addr,
const u8 *bssid, int id, int op_freq);
+void wpas_notify_mesh_group_started(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid);
+void wpas_notify_mesh_group_removed(struct wpa_supplicant *wpa_s,
+ const u8 *meshid, u8 meshid_len,
+ int reason_code);
+void wpas_notify_mesh_peer_connected(struct wpa_supplicant *wpa_s,
+ const u8 *peer_addr);
+void wpas_notify_mesh_peer_disconnected(struct wpa_supplicant *wpa_s,
+ const u8 *peer_addr, int reason_code);
#endif /* NOTIFY_H */
diff --git a/freebsd/contrib/wpa/wpa_supplicant/offchannel.c b/freebsd/contrib/wpa/wpa_supplicant/offchannel.c
index a269fdaf..fbf8ae12 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/offchannel.c
+++ b/freebsd/contrib/wpa/wpa_supplicant/offchannel.c
@@ -312,6 +312,8 @@ int offchannel_send_action(struct wpa_supplicant *wpa_s, unsigned int freq,
iface = wpas_get_tx_interface(wpa_s, src);
wpa_s->action_tx_wait_time = wait_time;
+ if (wait_time)
+ wpa_s->action_tx_wait_time_used = 1;
ret = wpa_drv_send_action(
iface, wpa_s->pending_action_freq,
@@ -400,13 +402,14 @@ void offchannel_send_action_done(struct wpa_supplicant *wpa_s)
wpabuf_free(wpa_s->pending_action_tx);
wpa_s->pending_action_tx = NULL;
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX &&
- wpa_s->action_tx_wait_time)
+ (wpa_s->action_tx_wait_time || wpa_s->action_tx_wait_time_used))
wpa_drv_send_action_cancel_wait(wpa_s);
else if (wpa_s->off_channel_freq || wpa_s->roc_waiting_drv_freq) {
wpa_drv_cancel_remain_on_channel(wpa_s);
wpa_s->off_channel_freq = 0;
wpa_s->roc_waiting_drv_freq = 0;
}
+ wpa_s->action_tx_wait_time_used = 0;
}
diff --git a/freebsd/contrib/wpa/wpa_supplicant/op_classes.c b/freebsd/contrib/wpa/wpa_supplicant/op_classes.c
new file mode 100644
index 00000000..8b517af7
--- /dev/null
+++ b/freebsd/contrib/wpa/wpa_supplicant/op_classes.c
@@ -0,0 +1,389 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Operating classes
+ * Copyright(c) 2015 Intel Deutschland GmbH
+ * Contact Information:
+ * Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+
+#include "utils/common.h"
+#include "common/ieee802_11_common.h"
+#include "wpa_supplicant_i.h"
+
+
+static enum chan_allowed allow_channel(struct hostapd_hw_modes *mode, u8 chan,
+ unsigned int *flags)
+{
+ int i;
+
+ for (i = 0; i < mode->num_channels; i++) {
+ if (mode->channels[i].chan == chan)
+ break;
+ }
+
+ if (i == mode->num_channels ||
+ (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED))
+ return NOT_ALLOWED;
+
+ if (flags)
+ *flags = mode->channels[i].flag;
+
+ if (mode->channels[i].flag & HOSTAPD_CHAN_NO_IR)
+ return NO_IR;
+
+ return ALLOWED;
+}
+
+
+static int get_center_80mhz(struct hostapd_hw_modes *mode, u8 channel)
+{
+ u8 center_channels[] = { 42, 58, 106, 122, 138, 155 };
+ size_t i;
+
+ if (mode->mode != HOSTAPD_MODE_IEEE80211A)
+ return 0;
+
+ for (i = 0; i < ARRAY_SIZE(center_channels); i++) {
+ /*
+ * In 80 MHz, the bandwidth "spans" 12 channels (e.g., 36-48),
+ * so the center channel is 6 channels away from the start/end.
+ */
+ if (channel >= center_channels[i] - 6 &&
+ channel <= center_channels[i] + 6)
+ return center_channels[i];
+ }
+
+ return 0;
+}
+
+
+static enum chan_allowed verify_80mhz(struct hostapd_hw_modes *mode, u8 channel)
+{
+ u8 center_chan;
+ unsigned int i;
+ unsigned int no_ir = 0;
+
+ center_chan = get_center_80mhz(mode, channel);
+ if (!center_chan)
+ return NOT_ALLOWED;
+
+ /* check all the channels are available */
+ for (i = 0; i < 4; i++) {
+ unsigned int flags;
+ u8 adj_chan = center_chan - 6 + i * 4;
+
+ if (allow_channel(mode, adj_chan, &flags) == NOT_ALLOWED)
+ return NOT_ALLOWED;
+
+ if ((i == 0 && !(flags & HOSTAPD_CHAN_VHT_10_70)) ||
+ (i == 1 && !(flags & HOSTAPD_CHAN_VHT_30_50)) ||
+ (i == 2 && !(flags & HOSTAPD_CHAN_VHT_50_30)) ||
+ (i == 3 && !(flags & HOSTAPD_CHAN_VHT_70_10)))
+ return NOT_ALLOWED;
+
+ if (flags & HOSTAPD_CHAN_NO_IR)
+ no_ir = 1;
+ }
+
+ if (no_ir)
+ return NO_IR;
+
+ return ALLOWED;
+}
+
+
+static int get_center_160mhz(struct hostapd_hw_modes *mode, u8 channel)
+{
+ u8 center_channels[] = { 50, 114 };
+ unsigned int i;
+
+ if (mode->mode != HOSTAPD_MODE_IEEE80211A)
+ return 0;
+
+ for (i = 0; i < ARRAY_SIZE(center_channels); i++) {
+ /*
+ * In 160 MHz, the bandwidth "spans" 28 channels (e.g., 36-64),
+ * so the center channel is 14 channels away from the start/end.
+ */
+ if (channel >= center_channels[i] - 14 &&
+ channel <= center_channels[i] + 14)
+ return center_channels[i];
+ }
+
+ return 0;
+}
+
+
+static enum chan_allowed verify_160mhz(struct hostapd_hw_modes *mode,
+ u8 channel)
+{
+ u8 center_chan;
+ unsigned int i;
+ unsigned int no_ir = 0;
+
+ center_chan = get_center_160mhz(mode, channel);
+ if (!center_chan)
+ return NOT_ALLOWED;
+
+ /* Check all the channels are available */
+ for (i = 0; i < 8; i++) {
+ unsigned int flags;
+ u8 adj_chan = center_chan - 14 + i * 4;
+
+ if (allow_channel(mode, adj_chan, &flags) == NOT_ALLOWED)
+ return NOT_ALLOWED;
+
+ if ((i == 0 && !(flags & HOSTAPD_CHAN_VHT_10_150)) ||
+ (i == 1 && !(flags & HOSTAPD_CHAN_VHT_30_130)) ||
+ (i == 2 && !(flags & HOSTAPD_CHAN_VHT_50_110)) ||
+ (i == 3 && !(flags & HOSTAPD_CHAN_VHT_70_90)) ||
+ (i == 4 && !(flags & HOSTAPD_CHAN_VHT_90_70)) ||
+ (i == 5 && !(flags & HOSTAPD_CHAN_VHT_110_50)) ||
+ (i == 6 && !(flags & HOSTAPD_CHAN_VHT_130_30)) ||
+ (i == 7 && !(flags & HOSTAPD_CHAN_VHT_150_10)))
+ return NOT_ALLOWED;
+
+ if (flags & HOSTAPD_CHAN_NO_IR)
+ no_ir = 1;
+ }
+
+ if (no_ir)
+ return NO_IR;
+
+ return ALLOWED;
+}
+
+
+enum chan_allowed verify_channel(struct hostapd_hw_modes *mode, u8 channel,
+ u8 bw)
+{
+ unsigned int flag = 0;
+ enum chan_allowed res, res2;
+
+ res2 = res = allow_channel(mode, channel, &flag);
+ if (bw == BW40MINUS) {
+ if (!(flag & HOSTAPD_CHAN_HT40MINUS))
+ return NOT_ALLOWED;
+ res2 = allow_channel(mode, channel - 4, NULL);
+ } else if (bw == BW40PLUS) {
+ if (!(flag & HOSTAPD_CHAN_HT40PLUS))
+ return NOT_ALLOWED;
+ res2 = allow_channel(mode, channel + 4, NULL);
+ } else if (bw == BW80) {
+ /*
+ * channel is a center channel and as such, not necessarily a
+ * valid 20 MHz channels. Override earlier allow_channel()
+ * result and use only the 80 MHz specific version.
+ */
+ res2 = res = verify_80mhz(mode, channel);
+ } else if (bw == BW160) {
+ /*
+ * channel is a center channel and as such, not necessarily a
+ * valid 20 MHz channels. Override earlier allow_channel()
+ * result and use only the 160 MHz specific version.
+ */
+ res2 = res = verify_160mhz(mode, channel);
+ } else if (bw == BW80P80) {
+ /*
+ * channel is a center channel and as such, not necessarily a
+ * valid 20 MHz channels. Override earlier allow_channel()
+ * result and use only the 80 MHz specific version.
+ */
+ res2 = res = verify_80mhz(mode, channel);
+ }
+
+ if (res == NOT_ALLOWED || res2 == NOT_ALLOWED)
+ return NOT_ALLOWED;
+
+ if (res == NO_IR || res2 == NO_IR)
+ return NO_IR;
+
+ return ALLOWED;
+}
+
+
+static int wpas_op_class_supported(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid,
+ const struct oper_class_map *op_class)
+{
+ int chan;
+ size_t i;
+ struct hostapd_hw_modes *mode;
+ int found;
+ int z;
+ int freq2 = 0;
+ int freq5 = 0;
+
+ mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, op_class->mode);
+ if (!mode)
+ return 0;
+
+ /* If we are configured to disable certain things, take that into
+ * account here. */
+ if (ssid->freq_list && ssid->freq_list[0]) {
+ for (z = 0; ; z++) {
+ int f = ssid->freq_list[z];
+
+ if (f == 0)
+ break; /* end of list */
+ if (f > 4000 && f < 6000)
+ freq5 = 1;
+ else if (f > 2400 && f < 2500)
+ freq2 = 1;
+ }
+ } else {
+ /* No frequencies specified, can use anything hardware supports.
+ */
+ freq2 = freq5 = 1;
+ }
+
+ if (op_class->op_class >= 115 && op_class->op_class <= 130 && !freq5)
+ return 0;
+ if (op_class->op_class >= 81 && op_class->op_class <= 84 && !freq2)
+ return 0;
+
+#ifdef CONFIG_HT_OVERRIDES
+ if (ssid->disable_ht) {
+ switch (op_class->op_class) {
+ case 83:
+ case 84:
+ case 104:
+ case 105:
+ case 116:
+ case 117:
+ case 119:
+ case 120:
+ case 122:
+ case 123:
+ case 126:
+ case 127:
+ case 128:
+ case 129:
+ case 130:
+ /* Disable >= 40 MHz channels if HT is disabled */
+ return 0;
+ }
+ }
+#endif /* CONFIG_HT_OVERRIDES */
+
+#ifdef CONFIG_VHT_OVERRIDES
+ if (ssid->disable_vht) {
+ if (op_class->op_class >= 128 && op_class->op_class <= 130) {
+ /* Disable >= 80 MHz channels if VHT is disabled */
+ return 0;
+ }
+ }
+#endif /* CONFIG_VHT_OVERRIDES */
+
+ if (op_class->op_class == 128) {
+ u8 channels[] = { 42, 58, 106, 122, 138, 155 };
+
+ for (i = 0; i < ARRAY_SIZE(channels); i++) {
+ if (verify_channel(mode, channels[i], op_class->bw) !=
+ NOT_ALLOWED)
+ return 1;
+ }
+
+ return 0;
+ }
+
+ if (op_class->op_class == 129) {
+ /* Check if either 160 MHz channels is allowed */
+ return verify_channel(mode, 50, op_class->bw) != NOT_ALLOWED ||
+ verify_channel(mode, 114, op_class->bw) != NOT_ALLOWED;
+ }
+
+ if (op_class->op_class == 130) {
+ /* Need at least two non-contiguous 80 MHz segments */
+ found = 0;
+
+ if (verify_channel(mode, 42, op_class->bw) != NOT_ALLOWED ||
+ verify_channel(mode, 58, op_class->bw) != NOT_ALLOWED)
+ found++;
+ if (verify_channel(mode, 106, op_class->bw) != NOT_ALLOWED ||
+ verify_channel(mode, 122, op_class->bw) != NOT_ALLOWED ||
+ verify_channel(mode, 138, op_class->bw) != NOT_ALLOWED)
+ found++;
+ if (verify_channel(mode, 106, op_class->bw) != NOT_ALLOWED &&
+ verify_channel(mode, 138, op_class->bw) != NOT_ALLOWED)
+ found++;
+ if (verify_channel(mode, 155, op_class->bw) != NOT_ALLOWED)
+ found++;
+
+ if (found >= 2)
+ return 1;
+
+ return 0;
+ }
+
+ found = 0;
+ for (chan = op_class->min_chan; chan <= op_class->max_chan;
+ chan += op_class->inc) {
+ if (verify_channel(mode, chan, op_class->bw) != NOT_ALLOWED) {
+ found = 1;
+ break;
+ }
+ }
+
+ return found;
+}
+
+
+size_t wpas_supp_op_class_ie(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid,
+ int freq, u8 *pos, size_t len)
+{
+ struct wpabuf *buf;
+ u8 op, current, chan;
+ u8 *ie_len;
+ size_t res;
+
+ /*
+ * Assume 20 MHz channel for now.
+ * TODO: Use the secondary channel and VHT channel width that will be
+ * used after association.
+ */
+ if (ieee80211_freq_to_channel_ext(freq, 0, VHT_CHANWIDTH_USE_HT,
+ &current, &chan) == NUM_HOSTAPD_MODES)
+ return 0;
+
+ /*
+ * Need 3 bytes for EID, length, and current operating class, plus
+ * 1 byte for every other supported operating class.
+ */
+ buf = wpabuf_alloc(global_op_class_size + 3);
+ if (!buf)
+ return 0;
+
+ wpabuf_put_u8(buf, WLAN_EID_SUPPORTED_OPERATING_CLASSES);
+ /* Will set the length later, putting a placeholder */
+ ie_len = wpabuf_put(buf, 1);
+ wpabuf_put_u8(buf, current);
+
+ for (op = 0; global_op_class[op].op_class; op++) {
+ if (wpas_op_class_supported(wpa_s, ssid, &global_op_class[op]))
+ wpabuf_put_u8(buf, global_op_class[op].op_class);
+ }
+
+ *ie_len = wpabuf_len(buf) - 2;
+ if (*ie_len < 2 || wpabuf_len(buf) > len) {
+ wpa_printf(MSG_ERROR,
+ "Failed to add supported operating classes IE");
+ res = 0;
+ } else {
+ os_memcpy(pos, wpabuf_head(buf), wpabuf_len(buf));
+ res = wpabuf_len(buf);
+ wpa_hexdump_buf(MSG_DEBUG,
+ "Added supported operating classes IE", buf);
+ }
+
+ wpabuf_free(buf);
+ return res;
+}
diff --git a/freebsd/contrib/wpa/wpa_supplicant/p2p_supplicant.h b/freebsd/contrib/wpa/wpa_supplicant/p2p_supplicant.h
index 63910d1c..24ec2caf 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/p2p_supplicant.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/p2p_supplicant.h
@@ -37,18 +37,18 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
int persistent_group, int auto_join, int join, int auth,
int go_intent, int freq, unsigned int vht_center_freq2,
int persistent_id, int pd, int ht40, int vht,
- unsigned int vht_chwidth, const u8 *group_ssid,
+ unsigned int vht_chwidth, int he, const u8 *group_ssid,
size_t group_ssid_len);
int wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s,
int freq, struct wpa_ssid *ssid);
int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
int freq, int vht_center_freq2, int ht40, int vht,
- int max_oper_chwidth);
+ int max_oper_chwidth, int he);
int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid, int addr_allocated,
int force_freq, int neg_freq,
int vht_center_freq2, int ht40,
- int vht, int max_oper_chwidth,
+ int vht, int max_oper_chwidth, int he,
const struct p2p_channels *channels,
int connection_timeout, int force_scan);
struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s,
@@ -117,7 +117,7 @@ int wpas_p2p_reject(struct wpa_supplicant *wpa_s, const u8 *addr);
int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq,
int vht_center_freq2, int ht40, int vht,
- int max_oper_chwidth, int pref_freq);
+ int max_oper_chwidth, int pref_freq, int he);
int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
const u8 *peer_addr, const u8 *go_dev_addr);
int wpas_p2p_presence_req(struct wpa_supplicant *wpa_s, u32 duration1,
@@ -211,6 +211,7 @@ int wpas_p2p_lo_start(struct wpa_supplicant *wpa_s, unsigned int freq,
unsigned int period, unsigned int interval,
unsigned int count);
int wpas_p2p_lo_stop(struct wpa_supplicant *wpa_s);
+int wpas_p2p_mac_setup(struct wpa_supplicant *wpa_s);
#else /* CONFIG_P2P */
diff --git a/freebsd/contrib/wpa/wpa_supplicant/rrm.c b/freebsd/contrib/wpa/wpa_supplicant/rrm.c
new file mode 100644
index 00000000..8cff1253
--- /dev/null
+++ b/freebsd/contrib/wpa/wpa_supplicant/rrm.c
@@ -0,0 +1,1577 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * wpa_supplicant - Radio Measurements
+ * Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "includes.h"
+
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "common/ieee802_11_common.h"
+#include "wpa_supplicant_i.h"
+#include "driver_i.h"
+#include "bss.h"
+#include "scan.h"
+#include "p2p_supplicant.h"
+
+
+static void wpas_rrm_neighbor_rep_timeout_handler(void *data, void *user_ctx)
+{
+ struct rrm_data *rrm = data;
+
+ if (!rrm->notify_neighbor_rep) {
+ wpa_printf(MSG_ERROR,
+ "RRM: Unexpected neighbor report timeout");
+ return;
+ }
+
+ wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report - NONE");
+ rrm->notify_neighbor_rep(rrm->neighbor_rep_cb_ctx, NULL);
+
+ rrm->notify_neighbor_rep = NULL;
+ rrm->neighbor_rep_cb_ctx = NULL;
+}
+
+
+/*
+ * wpas_rrm_reset - Clear and reset all RRM data in wpa_supplicant
+ * @wpa_s: Pointer to wpa_supplicant
+ */
+void wpas_rrm_reset(struct wpa_supplicant *wpa_s)
+{
+ wpa_s->rrm.rrm_used = 0;
+
+ eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
+ NULL);
+ if (wpa_s->rrm.notify_neighbor_rep)
+ wpas_rrm_neighbor_rep_timeout_handler(&wpa_s->rrm, NULL);
+ wpa_s->rrm.next_neighbor_rep_token = 1;
+ wpas_clear_beacon_rep_data(wpa_s);
+}
+
+
+/*
+ * wpas_rrm_process_neighbor_rep - Handle incoming neighbor report
+ * @wpa_s: Pointer to wpa_supplicant
+ * @report: Neighbor report buffer, prefixed by a 1-byte dialog token
+ * @report_len: Length of neighbor report buffer
+ */
+void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s,
+ const u8 *report, size_t report_len)
+{
+ struct wpabuf *neighbor_rep;
+
+ wpa_hexdump(MSG_DEBUG, "RRM: New Neighbor Report", report, report_len);
+ if (report_len < 1)
+ return;
+
+ if (report[0] != wpa_s->rrm.next_neighbor_rep_token - 1) {
+ wpa_printf(MSG_DEBUG,
+ "RRM: Discarding neighbor report with token %d (expected %d)",
+ report[0], wpa_s->rrm.next_neighbor_rep_token - 1);
+ return;
+ }
+
+ eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
+ NULL);
+
+ if (!wpa_s->rrm.notify_neighbor_rep) {
+ wpa_printf(MSG_ERROR, "RRM: Unexpected neighbor report");
+ return;
+ }
+
+ /* skipping the first byte, which is only an id (dialog token) */
+ neighbor_rep = wpabuf_alloc(report_len - 1);
+ if (!neighbor_rep) {
+ wpas_rrm_neighbor_rep_timeout_handler(&wpa_s->rrm, NULL);
+ return;
+ }
+ wpabuf_put_data(neighbor_rep, report + 1, report_len - 1);
+ wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report (token = %d)",
+ report[0]);
+ wpa_s->rrm.notify_neighbor_rep(wpa_s->rrm.neighbor_rep_cb_ctx,
+ neighbor_rep);
+ wpa_s->rrm.notify_neighbor_rep = NULL;
+ wpa_s->rrm.neighbor_rep_cb_ctx = NULL;
+}
+
+
+#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS)
+/* Workaround different, undefined for Windows, error codes used here */
+#define ENOTCONN -1
+#define EOPNOTSUPP -1
+#define ECANCELED -1
+#endif
+
+/* Measurement Request element + Location Subject + Maximum Age subelement */
+#define MEASURE_REQUEST_LCI_LEN (3 + 1 + 4)
+/* Measurement Request element + Location Civic Request */
+#define MEASURE_REQUEST_CIVIC_LEN (3 + 5)
+
+
+/**
+ * wpas_rrm_send_neighbor_rep_request - Request a neighbor report from our AP
+ * @wpa_s: Pointer to wpa_supplicant
+ * @ssid: if not null, this is sent in the request. Otherwise, no SSID IE
+ * is sent in the request.
+ * @lci: if set, neighbor request will include LCI request
+ * @civic: if set, neighbor request will include civic location request
+ * @cb: Callback function to be called once the requested report arrives, or
+ * timed out after RRM_NEIGHBOR_REPORT_TIMEOUT seconds.
+ * In the former case, 'neighbor_rep' is a newly allocated wpabuf, and it's
+ * the requester's responsibility to free it.
+ * In the latter case NULL will be sent in 'neighbor_rep'.
+ * @cb_ctx: Context value to send the callback function
+ * Returns: 0 in case of success, negative error code otherwise
+ *
+ * In case there is a previous request which has not been answered yet, the
+ * new request fails. The caller may retry after RRM_NEIGHBOR_REPORT_TIMEOUT.
+ * Request must contain a callback function.
+ */
+int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
+ const struct wpa_ssid_value *ssid,
+ int lci, int civic,
+ void (*cb)(void *ctx,
+ struct wpabuf *neighbor_rep),
+ void *cb_ctx)
+{
+ struct wpabuf *buf;
+ const u8 *rrm_ie;
+
+ if (wpa_s->wpa_state != WPA_COMPLETED || wpa_s->current_ssid == NULL) {
+ wpa_printf(MSG_DEBUG, "RRM: No connection, no RRM.");
+ return -ENOTCONN;
+ }
+
+ if (!wpa_s->rrm.rrm_used) {
+ wpa_printf(MSG_DEBUG, "RRM: No RRM in current connection.");
+ return -EOPNOTSUPP;
+ }
+
+ rrm_ie = wpa_bss_get_ie(wpa_s->current_bss,
+ WLAN_EID_RRM_ENABLED_CAPABILITIES);
+ if (!rrm_ie || !(wpa_s->current_bss->caps & IEEE80211_CAP_RRM) ||
+ !(rrm_ie[2] & WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
+ wpa_printf(MSG_DEBUG,
+ "RRM: No network support for Neighbor Report.");
+ return -EOPNOTSUPP;
+ }
+
+ /* Refuse if there's a live request */
+ if (wpa_s->rrm.notify_neighbor_rep) {
+ wpa_printf(MSG_DEBUG,
+ "RRM: Currently handling previous Neighbor Report.");
+ return -EBUSY;
+ }
+
+ /* 3 = action category + action code + dialog token */
+ buf = wpabuf_alloc(3 + (ssid ? 2 + ssid->ssid_len : 0) +
+ (lci ? 2 + MEASURE_REQUEST_LCI_LEN : 0) +
+ (civic ? 2 + MEASURE_REQUEST_CIVIC_LEN : 0));
+ if (buf == NULL) {
+ wpa_printf(MSG_DEBUG,
+ "RRM: Failed to allocate Neighbor Report Request");
+ return -ENOMEM;
+ }
+
+ wpa_printf(MSG_DEBUG, "RRM: Neighbor report request (for %s), token=%d",
+ (ssid ? wpa_ssid_txt(ssid->ssid, ssid->ssid_len) : ""),
+ wpa_s->rrm.next_neighbor_rep_token);
+
+ wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
+ wpabuf_put_u8(buf, WLAN_RRM_NEIGHBOR_REPORT_REQUEST);
+ wpabuf_put_u8(buf, wpa_s->rrm.next_neighbor_rep_token);
+ if (ssid) {
+ wpabuf_put_u8(buf, WLAN_EID_SSID);
+ wpabuf_put_u8(buf, ssid->ssid_len);
+ wpabuf_put_data(buf, ssid->ssid, ssid->ssid_len);
+ }
+
+ if (lci) {
+ /* IEEE P802.11-REVmc/D5.0 9.4.2.21 */
+ wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST);
+ wpabuf_put_u8(buf, MEASURE_REQUEST_LCI_LEN);
+
+ /*
+ * Measurement token; nonzero number that is unique among the
+ * Measurement Request elements in a particular frame.
+ */
+ wpabuf_put_u8(buf, 1); /* Measurement Token */
+
+ /*
+ * Parallel, Enable, Request, and Report bits are 0, Duration is
+ * reserved.
+ */
+ wpabuf_put_u8(buf, 0); /* Measurement Request Mode */
+ wpabuf_put_u8(buf, MEASURE_TYPE_LCI); /* Measurement Type */
+
+ /* IEEE P802.11-REVmc/D5.0 9.4.2.21.10 - LCI request */
+ /* Location Subject */
+ wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE);
+
+ /* Optional Subelements */
+ /*
+ * IEEE P802.11-REVmc/D5.0 Figure 9-170
+ * The Maximum Age subelement is required, otherwise the AP can
+ * send only data that was determined after receiving the
+ * request. Setting it here to unlimited age.
+ */
+ wpabuf_put_u8(buf, LCI_REQ_SUBELEM_MAX_AGE);
+ wpabuf_put_u8(buf, 2);
+ wpabuf_put_le16(buf, 0xffff);
+ }
+
+ if (civic) {
+ /* IEEE P802.11-REVmc/D5.0 9.4.2.21 */
+ wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST);
+ wpabuf_put_u8(buf, MEASURE_REQUEST_CIVIC_LEN);
+
+ /*
+ * Measurement token; nonzero number that is unique among the
+ * Measurement Request elements in a particular frame.
+ */
+ wpabuf_put_u8(buf, 2); /* Measurement Token */
+
+ /*
+ * Parallel, Enable, Request, and Report bits are 0, Duration is
+ * reserved.
+ */
+ wpabuf_put_u8(buf, 0); /* Measurement Request Mode */
+ /* Measurement Type */
+ wpabuf_put_u8(buf, MEASURE_TYPE_LOCATION_CIVIC);
+
+ /* IEEE P802.11-REVmc/D5.0 9.4.2.21.14:
+ * Location Civic request */
+ /* Location Subject */
+ wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE);
+ wpabuf_put_u8(buf, 0); /* Civic Location Type: IETF RFC 4776 */
+ /* Location Service Interval Units: Seconds */
+ wpabuf_put_u8(buf, 0);
+ /* Location Service Interval: 0 - Only one report is requested
+ */
+ wpabuf_put_le16(buf, 0);
+ /* No optional subelements */
+ }
+
+ wpa_s->rrm.next_neighbor_rep_token++;
+
+ if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
+ wpa_s->own_addr, wpa_s->bssid,
+ wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
+ wpa_printf(MSG_DEBUG,
+ "RRM: Failed to send Neighbor Report Request");
+ wpabuf_free(buf);
+ return -ECANCELED;
+ }
+
+ wpa_s->rrm.neighbor_rep_cb_ctx = cb_ctx;
+ wpa_s->rrm.notify_neighbor_rep = cb;
+ eloop_register_timeout(RRM_NEIGHBOR_REPORT_TIMEOUT, 0,
+ wpas_rrm_neighbor_rep_timeout_handler,
+ &wpa_s->rrm, NULL);
+
+ wpabuf_free(buf);
+ return 0;
+}
+
+
+static int wpas_rrm_report_elem(struct wpabuf **buf, u8 token, u8 mode, u8 type,
+ const u8 *data, size_t data_len)
+{
+ if (wpabuf_resize(buf, 5 + data_len))
+ return -1;
+
+ wpabuf_put_u8(*buf, WLAN_EID_MEASURE_REPORT);
+ wpabuf_put_u8(*buf, 3 + data_len);
+ wpabuf_put_u8(*buf, token);
+ wpabuf_put_u8(*buf, mode);
+ wpabuf_put_u8(*buf, type);
+
+ if (data_len)
+ wpabuf_put_data(*buf, data, data_len);
+
+ return 0;
+}
+
+
+static int
+wpas_rrm_build_lci_report(struct wpa_supplicant *wpa_s,
+ const struct rrm_measurement_request_element *req,
+ struct wpabuf **buf)
+{
+ u8 subject;
+ u16 max_age = 0;
+ struct os_reltime t, diff;
+ unsigned long diff_l;
+ const u8 *subelem;
+ const u8 *request = req->variable;
+ size_t len = req->len - 3;
+
+ if (len < 1)
+ return -1;
+
+ if (!wpa_s->lci)
+ goto reject;
+
+ subject = *request++;
+ len--;
+
+ wpa_printf(MSG_DEBUG, "Measurement request location subject=%u",
+ subject);
+
+ if (subject != LOCATION_SUBJECT_REMOTE) {
+ wpa_printf(MSG_INFO,
+ "Not building LCI report - bad location subject");
+ return 0;
+ }
+
+ /* Subelements are formatted exactly like elements */
+ wpa_hexdump(MSG_DEBUG, "LCI request subelements", request, len);
+ subelem = get_ie(request, len, LCI_REQ_SUBELEM_MAX_AGE);
+ if (subelem && subelem[1] == 2)
+ max_age = WPA_GET_LE16(subelem + 2);
+
+ if (os_get_reltime(&t))
+ goto reject;
+
+ os_reltime_sub(&t, &wpa_s->lci_time, &diff);
+ /* LCI age is calculated in 10th of a second units. */
+ diff_l = diff.sec * 10 + diff.usec / 100000;
+
+ if (max_age != 0xffff && max_age < diff_l)
+ goto reject;
+
+ if (wpas_rrm_report_elem(buf, req->token,
+ MEASUREMENT_REPORT_MODE_ACCEPT, req->type,
+ wpabuf_head_u8(wpa_s->lci),
+ wpabuf_len(wpa_s->lci)) < 0) {
+ wpa_printf(MSG_DEBUG, "Failed to add LCI report element");
+ return -1;
+ }
+
+ return 0;
+
+reject:
+ if (!is_multicast_ether_addr(wpa_s->rrm.dst_addr) &&
+ wpas_rrm_report_elem(buf, req->token,
+ MEASUREMENT_REPORT_MODE_REJECT_INCAPABLE,
+ req->type, NULL, 0) < 0) {
+ wpa_printf(MSG_DEBUG, "RRM: Failed to add report element");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static void wpas_rrm_send_msr_report_mpdu(struct wpa_supplicant *wpa_s,
+ const u8 *data, size_t len)
+{
+ struct wpabuf *report = wpabuf_alloc(len + 3);
+
+ if (!report)
+ return;
+
+ wpabuf_put_u8(report, WLAN_ACTION_RADIO_MEASUREMENT);
+ wpabuf_put_u8(report, WLAN_RRM_RADIO_MEASUREMENT_REPORT);
+ wpabuf_put_u8(report, wpa_s->rrm.token);
+
+ wpabuf_put_data(report, data, len);
+
+ if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
+ wpa_s->own_addr, wpa_s->bssid,
+ wpabuf_head(report), wpabuf_len(report), 0)) {
+ wpa_printf(MSG_ERROR,
+ "RRM: Radio measurement report failed: Sending Action frame failed");
+ }
+
+ wpabuf_free(report);
+}
+
+
+static int wpas_rrm_beacon_rep_update_last_frame(u8 *pos, size_t len)
+{
+ struct rrm_measurement_report_element *msr_rep;
+ u8 *end = pos + len;
+ u8 *msr_rep_end;
+ struct rrm_measurement_beacon_report *rep = NULL;
+ u8 *subelem;
+
+ /* Find the last beacon report element */
+ while (end - pos >= (int) sizeof(*msr_rep)) {
+ msr_rep = (struct rrm_measurement_report_element *) pos;
+ msr_rep_end = pos + msr_rep->len + 2;
+
+ if (msr_rep->eid != WLAN_EID_MEASURE_REPORT ||
+ msr_rep_end > end) {
+ /* Should not happen. This indicates a bug. */
+ wpa_printf(MSG_ERROR,
+ "RRM: non-measurement report element in measurement report frame");
+ return -1;
+ }
+
+ if (msr_rep->type == MEASURE_TYPE_BEACON)
+ rep = (struct rrm_measurement_beacon_report *)
+ msr_rep->variable;
+
+ pos += pos[1] + 2;
+ }
+
+ if (!rep)
+ return 0;
+
+ subelem = rep->variable;
+ while (subelem + 2 < msr_rep_end &&
+ subelem[0] != WLAN_BEACON_REPORT_SUBELEM_LAST_INDICATION)
+ subelem += 2 + subelem[1];
+
+ if (subelem + 2 < msr_rep_end &&
+ subelem[0] == WLAN_BEACON_REPORT_SUBELEM_LAST_INDICATION &&
+ subelem[1] == 1 &&
+ subelem + BEACON_REPORT_LAST_INDICATION_SUBELEM_LEN <= end)
+ subelem[2] = 1;
+
+ return 0;
+}
+
+
+static void wpas_rrm_send_msr_report(struct wpa_supplicant *wpa_s,
+ struct wpabuf *buf)
+{
+ int len = wpabuf_len(buf);
+ u8 *pos = wpabuf_mhead_u8(buf), *next = pos;
+
+#define MPDU_REPORT_LEN (int) (IEEE80211_MAX_MMPDU_SIZE - IEEE80211_HDRLEN - 3)
+
+ while (len) {
+ int send_len = (len > MPDU_REPORT_LEN) ? next - pos : len;
+
+ if (send_len == len)
+ wpas_rrm_beacon_rep_update_last_frame(pos, len);
+
+ if (send_len == len ||
+ (send_len + next[1] + 2) > MPDU_REPORT_LEN) {
+ wpas_rrm_send_msr_report_mpdu(wpa_s, pos, send_len);
+ len -= send_len;
+ pos = next;
+ }
+
+ if (len)
+ next += next[1] + 2;
+ }
+#undef MPDU_REPORT_LEN
+}
+
+
+static int wpas_add_channel(u8 op_class, u8 chan, u8 num_primary_channels,
+ int *freqs)
+{
+ size_t i;
+
+ for (i = 0; i < num_primary_channels; i++) {
+ u8 primary_chan = chan - (2 * num_primary_channels - 2) + i * 4;
+
+ freqs[i] = ieee80211_chan_to_freq(NULL, op_class, primary_chan);
+ /* ieee80211_chan_to_freq() is not really meant for this
+ * conversion of 20 MHz primary channel numbers for wider VHT
+ * channels, so handle those as special cases here for now. */
+ if (freqs[i] < 0 &&
+ (op_class == 128 || op_class == 129 || op_class == 130))
+ freqs[i] = 5000 + 5 * primary_chan;
+ if (freqs[i] < 0) {
+ wpa_printf(MSG_DEBUG,
+ "Beacon Report: Invalid channel %u",
+ chan);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+
+static int * wpas_add_channels(const struct oper_class_map *op,
+ struct hostapd_hw_modes *mode, int active,
+ const u8 *channels, const u8 size)
+{
+ int *freqs, *next_freq;
+ u8 num_primary_channels, i;
+ u8 num_chans;
+
+ num_chans = channels ? size :
+ (op->max_chan - op->min_chan) / op->inc + 1;
+
+ if (op->bw == BW80 || op->bw == BW80P80)
+ num_primary_channels = 4;
+ else if (op->bw == BW160)
+ num_primary_channels = 8;
+ else
+ num_primary_channels = 1;
+
+ /* one extra place for the zero-terminator */
+ freqs = os_calloc(num_chans * num_primary_channels + 1, sizeof(*freqs));
+ if (!freqs) {
+ wpa_printf(MSG_ERROR,
+ "Beacon Report: Failed to allocate freqs array");
+ return NULL;
+ }
+
+ next_freq = freqs;
+ for (i = 0; i < num_chans; i++) {
+ u8 chan = channels ? channels[i] : op->min_chan + i * op->inc;
+ enum chan_allowed res = verify_channel(mode, chan, op->bw);
+
+ if (res == NOT_ALLOWED || (res == NO_IR && active))
+ continue;
+
+ if (wpas_add_channel(op->op_class, chan, num_primary_channels,
+ next_freq) < 0) {
+ os_free(freqs);
+ return NULL;
+ }
+
+ next_freq += num_primary_channels;
+ }
+
+ if (!freqs[0]) {
+ os_free(freqs);
+ return NULL;
+ }
+
+ return freqs;
+}
+
+
+static int * wpas_op_class_freqs(const struct oper_class_map *op,
+ struct hostapd_hw_modes *mode, int active)
+{
+ u8 channels_80mhz[] = { 42, 58, 106, 122, 138, 155 };
+ u8 channels_160mhz[] = { 50, 114 };
+
+ /*
+ * When adding all channels in the operating class, 80 + 80 MHz
+ * operating classes are like 80 MHz channels because we add all valid
+ * channels anyway.
+ */
+ if (op->bw == BW80 || op->bw == BW80P80)
+ return wpas_add_channels(op, mode, active, channels_80mhz,
+ ARRAY_SIZE(channels_80mhz));
+
+ if (op->bw == BW160)
+ return wpas_add_channels(op, mode, active, channels_160mhz,
+ ARRAY_SIZE(channels_160mhz));
+
+ return wpas_add_channels(op, mode, active, NULL, 0);
+}
+
+
+static int * wpas_channel_report_freqs(struct wpa_supplicant *wpa_s, int active,
+ const char *country, const u8 *subelems,
+ size_t len)
+{
+ int *freqs = NULL, *new_freqs;
+ const u8 *end = subelems + len;
+
+ while (end - subelems > 2) {
+ const struct oper_class_map *op;
+ const u8 *ap_chan_elem, *pos;
+ u8 left;
+ struct hostapd_hw_modes *mode;
+
+ ap_chan_elem = get_ie(subelems, end - subelems,
+ WLAN_BEACON_REQUEST_SUBELEM_AP_CHANNEL);
+ if (!ap_chan_elem)
+ break;
+ pos = ap_chan_elem + 2;
+ left = ap_chan_elem[1];
+ if (left < 1)
+ break;
+ subelems = ap_chan_elem + 2 + left;
+
+ op = get_oper_class(country, *pos);
+ if (!op) {
+ wpa_printf(MSG_DEBUG,
+ "Beacon request: unknown operating class in AP Channel Report subelement %u",
+ *pos);
+ goto out;
+ }
+ pos++;
+ left--;
+
+ mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, op->mode);
+ if (!mode)
+ continue;
+
+ /*
+ * For 80 + 80 MHz operating classes, this AP Channel Report
+ * element should be followed by another element specifying
+ * the second 80 MHz channel. For now just add this 80 MHz
+ * channel, the second 80 MHz channel will be added when the
+ * next element is parsed.
+ * TODO: Verify that this AP Channel Report element is followed
+ * by a corresponding AP Channel Report element as specified in
+ * IEEE Std 802.11-2016, 11.11.9.1.
+ */
+ new_freqs = wpas_add_channels(op, mode, active, pos, left);
+ if (new_freqs)
+ int_array_concat(&freqs, new_freqs);
+
+ os_free(new_freqs);
+ }
+
+ return freqs;
+out:
+ os_free(freqs);
+ return NULL;
+}
+
+
+static int * wpas_beacon_request_freqs(struct wpa_supplicant *wpa_s,
+ u8 op_class, u8 chan, int active,
+ const u8 *subelems, size_t len)
+{
+ int *freqs = NULL, *ext_freqs = NULL;
+ struct hostapd_hw_modes *mode;
+ const char *country = NULL;
+ const struct oper_class_map *op;
+ const u8 *elem;
+
+ if (!wpa_s->current_bss)
+ return NULL;
+ elem = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_COUNTRY);
+ if (elem && elem[1] >= 2)
+ country = (const char *) (elem + 2);
+
+ op = get_oper_class(country, op_class);
+ if (!op) {
+ wpa_printf(MSG_DEBUG,
+ "Beacon request: invalid operating class %d",
+ op_class);
+ return NULL;
+ }
+
+ mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, op->mode);
+ if (!mode)
+ return NULL;
+
+ switch (chan) {
+ case 0:
+ freqs = wpas_op_class_freqs(op, mode, active);
+ if (!freqs)
+ return NULL;
+ break;
+ case 255:
+ /* freqs will be added from AP channel subelements */
+ break;
+ default:
+ freqs = wpas_add_channels(op, mode, active, &chan, 1);
+ if (!freqs)
+ return NULL;
+ break;
+ }
+
+ ext_freqs = wpas_channel_report_freqs(wpa_s, active, country, subelems,
+ len);
+ if (ext_freqs) {
+ int_array_concat(&freqs, ext_freqs);
+ os_free(ext_freqs);
+ int_array_sort_unique(freqs);
+ }
+
+ return freqs;
+}
+
+
+static int wpas_get_op_chan_phy(int freq, const u8 *ies, size_t ies_len,
+ u8 *op_class, u8 *chan, u8 *phy_type)
+{
+ const u8 *ie;
+ int sec_chan = 0, vht = 0;
+ struct ieee80211_ht_operation *ht_oper = NULL;
+ struct ieee80211_vht_operation *vht_oper = NULL;
+ u8 seg0, seg1;
+
+ ie = get_ie(ies, ies_len, WLAN_EID_HT_OPERATION);
+ if (ie && ie[1] >= sizeof(struct ieee80211_ht_operation)) {
+ u8 sec_chan_offset;
+
+ ht_oper = (struct ieee80211_ht_operation *) (ie + 2);
+ sec_chan_offset = ht_oper->ht_param &
+ HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
+ if (sec_chan_offset == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
+ sec_chan = 1;
+ else if (sec_chan_offset ==
+ HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
+ sec_chan = -1;
+ }
+
+ ie = get_ie(ies, ies_len, WLAN_EID_VHT_OPERATION);
+ if (ie && ie[1] >= sizeof(struct ieee80211_vht_operation)) {
+ vht_oper = (struct ieee80211_vht_operation *) (ie + 2);
+
+ switch (vht_oper->vht_op_info_chwidth) {
+ case 1:
+ seg0 = vht_oper->vht_op_info_chan_center_freq_seg0_idx;
+ seg1 = vht_oper->vht_op_info_chan_center_freq_seg1_idx;
+ if (seg1 && abs(seg1 - seg0) == 8)
+ vht = VHT_CHANWIDTH_160MHZ;
+ else if (seg1)
+ vht = VHT_CHANWIDTH_80P80MHZ;
+ else
+ vht = VHT_CHANWIDTH_80MHZ;
+ break;
+ case 2:
+ vht = VHT_CHANWIDTH_160MHZ;
+ break;
+ case 3:
+ vht = VHT_CHANWIDTH_80P80MHZ;
+ break;
+ default:
+ vht = VHT_CHANWIDTH_USE_HT;
+ break;
+ }
+ }
+
+ if (ieee80211_freq_to_channel_ext(freq, sec_chan, vht, op_class,
+ chan) == NUM_HOSTAPD_MODES) {
+ wpa_printf(MSG_DEBUG,
+ "Cannot determine operating class and channel");
+ return -1;
+ }
+
+ *phy_type = ieee80211_get_phy_type(freq, ht_oper != NULL,
+ vht_oper != NULL);
+ if (*phy_type == PHY_TYPE_UNSPECIFIED) {
+ wpa_printf(MSG_DEBUG, "Cannot determine phy type");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int wpas_beacon_rep_add_frame_body(struct bitfield *eids,
+ enum beacon_report_detail detail,
+ struct wpa_bss *bss, u8 *buf,
+ size_t buf_len, u8 **ies_buf,
+ size_t *ie_len, int add_fixed)
+{
+ u8 *ies = *ies_buf;
+ size_t ies_len = *ie_len;
+ u8 *pos = buf;
+ int rem_len;
+
+ rem_len = 255 - sizeof(struct rrm_measurement_beacon_report) -
+ sizeof(struct rrm_measurement_report_element) - 2 -
+ REPORTED_FRAME_BODY_SUBELEM_LEN;
+
+ if (detail > BEACON_REPORT_DETAIL_ALL_FIELDS_AND_ELEMENTS) {
+ wpa_printf(MSG_DEBUG,
+ "Beacon Request: Invalid reporting detail: %d",
+ detail);
+ return -1;
+ }
+
+ if (detail == BEACON_REPORT_DETAIL_NONE)
+ return 0;
+
+ /*
+ * Minimal frame body subelement size: EID(1) + length(1) + TSF(8) +
+ * beacon interval(2) + capabilities(2) = 14 bytes
+ */
+ if (add_fixed && buf_len < 14)
+ return -1;
+
+ *pos++ = WLAN_BEACON_REPORT_SUBELEM_FRAME_BODY;
+ /* The length will be filled later */
+ pos++;
+
+ if (add_fixed) {
+ WPA_PUT_LE64(pos, bss->tsf);
+ pos += sizeof(bss->tsf);
+ WPA_PUT_LE16(pos, bss->beacon_int);
+ pos += 2;
+ WPA_PUT_LE16(pos, bss->caps);
+ pos += 2;
+ }
+
+ rem_len -= pos - buf;
+
+ /*
+ * According to IEEE Std 802.11-2016, 9.4.2.22.7, if the reported frame
+ * body subelement causes the element to exceed the maximum element
+ * size, the subelement is truncated so that the last IE is a complete
+ * IE. So even when required to report all IEs, add elements one after
+ * the other and stop once there is no more room in the measurement
+ * element.
+ */
+ while (ies_len > 2 && 2U + ies[1] <= ies_len && rem_len > 0) {
+ if (detail == BEACON_REPORT_DETAIL_ALL_FIELDS_AND_ELEMENTS ||
+ (eids && bitfield_is_set(eids, ies[0]))) {
+ u8 elen = ies[1];
+
+ if (2 + elen > buf + buf_len - pos ||
+ 2 + elen > rem_len)
+ break;
+
+ *pos++ = ies[0];
+ *pos++ = elen;
+ os_memcpy(pos, ies + 2, elen);
+ pos += elen;
+ rem_len -= 2 + elen;
+ }
+
+ ies_len -= 2 + ies[1];
+ ies += 2 + ies[1];
+ }
+
+ *ie_len = ies_len;
+ *ies_buf = ies;
+
+ /* Now the length is known */
+ buf[1] = pos - buf - 2;
+ return pos - buf;
+}
+
+
+static int wpas_add_beacon_rep_elem(struct beacon_rep_data *data,
+ struct wpa_bss *bss,
+ struct wpabuf **wpa_buf,
+ struct rrm_measurement_beacon_report *rep,
+ u8 **ie, size_t *ie_len, u8 idx)
+{
+ int ret;
+ u8 *buf, *pos;
+ u32 subelems_len = REPORTED_FRAME_BODY_SUBELEM_LEN +
+ (data->last_indication ?
+ BEACON_REPORT_LAST_INDICATION_SUBELEM_LEN : 0);
+
+ /* Maximum element length: Beacon Report element + Reported Frame Body
+ * subelement + all IEs of the reported Beacon frame + Reported Frame
+ * Body Fragment ID subelement */
+ buf = os_malloc(sizeof(*rep) + 14 + *ie_len + subelems_len);
+ if (!buf)
+ return -1;
+
+ os_memcpy(buf, rep, sizeof(*rep));
+
+ ret = wpas_beacon_rep_add_frame_body(data->eids, data->report_detail,
+ bss, buf + sizeof(*rep),
+ 14 + *ie_len, ie, ie_len,
+ idx == 0);
+ if (ret < 0)
+ goto out;
+
+ pos = buf + ret + sizeof(*rep);
+ pos[0] = WLAN_BEACON_REPORT_SUBELEM_FRAME_BODY_FRAGMENT_ID;
+ pos[1] = 2;
+
+ /*
+ * Only one Beacon Report Measurement is supported at a time, so
+ * the Beacon Report ID can always be set to 1.
+ */
+ pos[2] = 1;
+
+ /* Fragment ID Number (bits 0..6) and More Frame Body Fragments (bit 7)
+ */
+ pos[3] = idx;
+ if (data->report_detail != BEACON_REPORT_DETAIL_NONE && *ie_len)
+ pos[3] |= REPORTED_FRAME_BODY_MORE_FRAGMENTS;
+ else
+ pos[3] &= ~REPORTED_FRAME_BODY_MORE_FRAGMENTS;
+
+ pos += REPORTED_FRAME_BODY_SUBELEM_LEN;
+
+ if (data->last_indication) {
+ pos[0] = WLAN_BEACON_REPORT_SUBELEM_LAST_INDICATION;
+ pos[1] = 1;
+
+ /* This field will be updated later if this is the last frame */
+ pos[2] = 0;
+ }
+
+ ret = wpas_rrm_report_elem(wpa_buf, data->token,
+ MEASUREMENT_REPORT_MODE_ACCEPT,
+ MEASURE_TYPE_BEACON, buf,
+ ret + sizeof(*rep) + subelems_len);
+out:
+ os_free(buf);
+ return ret;
+}
+
+
+static int wpas_add_beacon_rep(struct wpa_supplicant *wpa_s,
+ struct wpabuf **wpa_buf, struct wpa_bss *bss,
+ u64 start, u64 parent_tsf)
+{
+ struct beacon_rep_data *data = &wpa_s->beacon_rep_data;
+ u8 *ies = (u8 *) (bss + 1);
+ u8 *pos = ies;
+ size_t ies_len = bss->ie_len ? bss->ie_len : bss->beacon_ie_len;
+ struct rrm_measurement_beacon_report rep;
+ u8 idx = 0;
+
+ if (os_memcmp(data->bssid, broadcast_ether_addr, ETH_ALEN) != 0 &&
+ os_memcmp(data->bssid, bss->bssid, ETH_ALEN) != 0)
+ return 0;
+
+ if (data->ssid_len &&
+ (data->ssid_len != bss->ssid_len ||
+ os_memcmp(data->ssid, bss->ssid, bss->ssid_len) != 0))
+ return 0;
+
+ if (wpas_get_op_chan_phy(bss->freq, ies, ies_len, &rep.op_class,
+ &rep.channel, &rep.report_info) < 0)
+ return 0;
+
+ rep.start_time = host_to_le64(start);
+ rep.duration = host_to_le16(data->scan_params.duration);
+ rep.rcpi = rssi_to_rcpi(bss->level);
+ rep.rsni = 255; /* 255 indicates that RSNI is not available */
+ os_memcpy(rep.bssid, bss->bssid, ETH_ALEN);
+ rep.antenna_id = 0; /* unknown */
+ rep.parent_tsf = host_to_le32(parent_tsf);
+
+ do {
+ int ret;
+
+ ret = wpas_add_beacon_rep_elem(data, bss, wpa_buf, &rep,
+ &pos, &ies_len, idx++);
+ if (ret)
+ return ret;
+ } while (data->report_detail != BEACON_REPORT_DETAIL_NONE &&
+ ies_len >= 2);
+
+ return 0;
+}
+
+
+static int wpas_beacon_rep_no_results(struct wpa_supplicant *wpa_s,
+ struct wpabuf **buf)
+{
+ return wpas_rrm_report_elem(buf, wpa_s->beacon_rep_data.token,
+ MEASUREMENT_REPORT_MODE_ACCEPT,
+ MEASURE_TYPE_BEACON, NULL, 0);
+}
+
+
+static void wpas_beacon_rep_table(struct wpa_supplicant *wpa_s,
+ struct wpabuf **buf)
+{
+ size_t i;
+
+ for (i = 0; i < wpa_s->last_scan_res_used; i++) {
+ if (wpas_add_beacon_rep(wpa_s, buf, wpa_s->last_scan_res[i],
+ 0, 0) < 0)
+ break;
+ }
+
+ if (!(*buf))
+ wpas_beacon_rep_no_results(wpa_s, buf);
+
+ wpa_hexdump_buf(MSG_DEBUG, "RRM: Radio Measurement report", *buf);
+}
+
+
+void wpas_rrm_refuse_request(struct wpa_supplicant *wpa_s)
+{
+ if (!is_multicast_ether_addr(wpa_s->rrm.dst_addr)) {
+ struct wpabuf *buf = NULL;
+
+ if (wpas_rrm_report_elem(&buf, wpa_s->beacon_rep_data.token,
+ MEASUREMENT_REPORT_MODE_REJECT_REFUSED,
+ MEASURE_TYPE_BEACON, NULL, 0)) {
+ wpa_printf(MSG_ERROR, "RRM: Memory allocation failed");
+ wpabuf_free(buf);
+ return;
+ }
+
+ wpas_rrm_send_msr_report(wpa_s, buf);
+ wpabuf_free(buf);
+ }
+
+ wpas_clear_beacon_rep_data(wpa_s);
+}
+
+
+static void wpas_rrm_scan_timeout(void *eloop_ctx, void *timeout_ctx)
+{
+ struct wpa_supplicant *wpa_s = eloop_ctx;
+ struct wpa_driver_scan_params *params =
+ &wpa_s->beacon_rep_data.scan_params;
+ u16 prev_duration = params->duration;
+
+ if (!wpa_s->current_bss)
+ return;
+
+ if (!(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_SUPPORT_SET_SCAN_DWELL) &&
+ params->duration) {
+ wpa_printf(MSG_DEBUG,
+ "RRM: Cannot set scan duration due to missing driver support");
+ params->duration = 0;
+ }
+ os_get_reltime(&wpa_s->beacon_rep_scan);
+ if (wpa_s->scanning || wpas_p2p_in_progress(wpa_s) ||
+ wpa_supplicant_trigger_scan(wpa_s, params))
+ wpas_rrm_refuse_request(wpa_s);
+ params->duration = prev_duration;
+}
+
+
+static int wpas_rm_handle_beacon_req_subelem(struct wpa_supplicant *wpa_s,
+ struct beacon_rep_data *data,
+ u8 sid, u8 slen, const u8 *subelem)
+{
+ u8 report_info, i;
+
+ switch (sid) {
+ case WLAN_BEACON_REQUEST_SUBELEM_SSID:
+ if (!slen) {
+ wpa_printf(MSG_DEBUG,
+ "SSID subelement with zero length - wildcard SSID");
+ break;
+ }
+
+ if (slen > SSID_MAX_LEN) {
+ wpa_printf(MSG_DEBUG,
+ "Invalid SSID subelement length: %u", slen);
+ return -1;
+ }
+
+ data->ssid_len = slen;
+ os_memcpy(data->ssid, subelem, data->ssid_len);
+ break;
+ case WLAN_BEACON_REQUEST_SUBELEM_INFO:
+ if (slen != 2) {
+ wpa_printf(MSG_DEBUG,
+ "Invalid reporting information subelement length: %u",
+ slen);
+ return -1;
+ }
+
+ report_info = subelem[0];
+ if (report_info != 0) {
+ wpa_printf(MSG_DEBUG,
+ "reporting information=%u is not supported",
+ report_info);
+ return 0;
+ }
+ break;
+ case WLAN_BEACON_REQUEST_SUBELEM_DETAIL:
+ if (slen != 1) {
+ wpa_printf(MSG_DEBUG,
+ "Invalid reporting detail subelement length: %u",
+ slen);
+ return -1;
+ }
+
+ data->report_detail = subelem[0];
+ if (data->report_detail >
+ BEACON_REPORT_DETAIL_ALL_FIELDS_AND_ELEMENTS) {
+ wpa_printf(MSG_DEBUG, "Invalid reporting detail: %u",
+ subelem[0]);
+ return -1;
+ }
+
+ break;
+ case WLAN_BEACON_REQUEST_SUBELEM_REQUEST:
+ if (data->report_detail !=
+ BEACON_REPORT_DETAIL_REQUESTED_ONLY) {
+ wpa_printf(MSG_DEBUG,
+ "Beacon request: request subelement is present but report detail is %u",
+ data->report_detail);
+ return -1;
+ }
+
+ if (!slen) {
+ wpa_printf(MSG_DEBUG,
+ "Invalid request subelement length: %u",
+ slen);
+ return -1;
+ }
+
+ if (data->eids) {
+ wpa_printf(MSG_DEBUG,
+ "Beacon Request: Request subelement appears more than once");
+ return -1;
+ }
+
+ data->eids = bitfield_alloc(255);
+ if (!data->eids) {
+ wpa_printf(MSG_DEBUG, "Failed to allocate EIDs bitmap");
+ return -1;
+ }
+
+ for (i = 0; i < slen; i++)
+ bitfield_set(data->eids, subelem[i]);
+ break;
+ case WLAN_BEACON_REQUEST_SUBELEM_AP_CHANNEL:
+ /* Skip - it will be processed when freqs are added */
+ break;
+ case WLAN_BEACON_REQUEST_SUBELEM_LAST_INDICATION:
+ if (slen != 1) {
+ wpa_printf(MSG_DEBUG,
+ "Beacon request: Invalid last indication request subelement length: %u",
+ slen);
+ return -1;
+ }
+
+ data->last_indication = subelem[0];
+ break;
+ default:
+ wpa_printf(MSG_DEBUG,
+ "Beacon request: Unknown subelement id %u", sid);
+ break;
+ }
+
+ return 1;
+}
+
+
+/**
+ * Returns 0 if the next element can be processed, 1 if some operation was
+ * triggered, and -1 if processing failed (i.e., the element is in invalid
+ * format or an internal error occurred).
+ */
+static int
+wpas_rm_handle_beacon_req(struct wpa_supplicant *wpa_s,
+ u8 elem_token, int duration_mandatory,
+ const struct rrm_measurement_beacon_request *req,
+ size_t len, struct wpabuf **buf)
+{
+ struct beacon_rep_data *data = &wpa_s->beacon_rep_data;
+ struct wpa_driver_scan_params *params = &data->scan_params;
+ const u8 *subelems;
+ size_t elems_len;
+ u16 rand_interval;
+ u32 interval_usec;
+ u32 _rand;
+ int ret = 0, res;
+ u8 reject_mode;
+
+ if (len < sizeof(*req))
+ return -1;
+
+ if (req->mode != BEACON_REPORT_MODE_PASSIVE &&
+ req->mode != BEACON_REPORT_MODE_ACTIVE &&
+ req->mode != BEACON_REPORT_MODE_TABLE)
+ return 0;
+
+ subelems = req->variable;
+ elems_len = len - sizeof(*req);
+ rand_interval = le_to_host16(req->rand_interval);
+
+ os_free(params->freqs);
+ os_memset(params, 0, sizeof(*params));
+
+ data->token = elem_token;
+
+ /* default reporting detail is all fixed length fields and all
+ * elements */
+ data->report_detail = BEACON_REPORT_DETAIL_ALL_FIELDS_AND_ELEMENTS;
+ os_memcpy(data->bssid, req->bssid, ETH_ALEN);
+
+ while (elems_len >= 2) {
+ if (subelems[1] > elems_len - 2) {
+ wpa_printf(MSG_DEBUG,
+ "Beacon Request: Truncated subelement");
+ ret = -1;
+ goto out;
+ }
+
+ res = wpas_rm_handle_beacon_req_subelem(
+ wpa_s, data, subelems[0], subelems[1], &subelems[2]);
+ if (res < 0) {
+ ret = res;
+ goto out;
+ } else if (!res) {
+ reject_mode = MEASUREMENT_REPORT_MODE_REJECT_INCAPABLE;
+ goto out_reject;
+ }
+
+ elems_len -= 2 + subelems[1];
+ subelems += 2 + subelems[1];
+ }
+
+ if (req->mode == BEACON_REPORT_MODE_TABLE) {
+ wpas_beacon_rep_table(wpa_s, buf);
+ goto out;
+ }
+
+ params->freqs = wpas_beacon_request_freqs(
+ wpa_s, req->oper_class, req->channel,
+ req->mode == BEACON_REPORT_MODE_ACTIVE,
+ req->variable, len - sizeof(*req));
+ if (!params->freqs) {
+ wpa_printf(MSG_DEBUG, "Beacon request: No valid channels");
+ reject_mode = MEASUREMENT_REPORT_MODE_REJECT_REFUSED;
+ goto out_reject;
+ }
+
+ params->duration = le_to_host16(req->duration);
+ params->duration_mandatory = duration_mandatory;
+ if (!params->duration) {
+ wpa_printf(MSG_DEBUG, "Beacon request: Duration is 0");
+ ret = -1;
+ goto out;
+ }
+
+ params->only_new_results = 1;
+
+ if (req->mode == BEACON_REPORT_MODE_ACTIVE) {
+ params->ssids[params->num_ssids].ssid = data->ssid;
+ params->ssids[params->num_ssids++].ssid_len = data->ssid_len;
+ }
+
+ if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0)
+ _rand = os_random();
+ interval_usec = (_rand % (rand_interval + 1)) * 1024;
+ eloop_register_timeout(0, interval_usec, wpas_rrm_scan_timeout, wpa_s,
+ NULL);
+ return 1;
+out_reject:
+ if (!is_multicast_ether_addr(wpa_s->rrm.dst_addr) &&
+ wpas_rrm_report_elem(buf, elem_token, reject_mode,
+ MEASURE_TYPE_BEACON, NULL, 0) < 0) {
+ wpa_printf(MSG_DEBUG, "RRM: Failed to add report element");
+ ret = -1;
+ }
+out:
+ wpas_clear_beacon_rep_data(wpa_s);
+ return ret;
+}
+
+
+static int
+wpas_rrm_handle_msr_req_element(
+ struct wpa_supplicant *wpa_s,
+ const struct rrm_measurement_request_element *req,
+ struct wpabuf **buf)
+{
+ int duration_mandatory;
+
+ wpa_printf(MSG_DEBUG, "Measurement request type %d token %d",
+ req->type, req->token);
+
+ if (req->mode & MEASUREMENT_REQUEST_MODE_ENABLE) {
+ /* Enable bit is not supported for now */
+ wpa_printf(MSG_DEBUG, "RRM: Enable bit not supported, ignore");
+ return 0;
+ }
+
+ if ((req->mode & MEASUREMENT_REQUEST_MODE_PARALLEL) &&
+ req->type > MEASURE_TYPE_RPI_HIST) {
+ /* Parallel measurements are not supported for now */
+ wpa_printf(MSG_DEBUG,
+ "RRM: Parallel measurements are not supported, reject");
+ goto reject;
+ }
+
+ duration_mandatory =
+ !!(req->mode & MEASUREMENT_REQUEST_MODE_DURATION_MANDATORY);
+
+ switch (req->type) {
+ case MEASURE_TYPE_LCI:
+ return wpas_rrm_build_lci_report(wpa_s, req, buf);
+ case MEASURE_TYPE_BEACON:
+ if (duration_mandatory &&
+ !(wpa_s->drv_rrm_flags &
+ WPA_DRIVER_FLAGS_SUPPORT_SET_SCAN_DWELL)) {
+ wpa_printf(MSG_DEBUG,
+ "RRM: Driver does not support dwell time configuration - reject beacon report with mandatory duration");
+ goto reject;
+ }
+ return wpas_rm_handle_beacon_req(wpa_s, req->token,
+ duration_mandatory,
+ (const void *) req->variable,
+ req->len - 3, buf);
+ default:
+ wpa_printf(MSG_INFO,
+ "RRM: Unsupported radio measurement type %u",
+ req->type);
+ break;
+ }
+
+reject:
+ if (!is_multicast_ether_addr(wpa_s->rrm.dst_addr) &&
+ wpas_rrm_report_elem(buf, req->token,
+ MEASUREMENT_REPORT_MODE_REJECT_INCAPABLE,
+ req->type, NULL, 0) < 0) {
+ wpa_printf(MSG_DEBUG, "RRM: Failed to add report element");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static struct wpabuf *
+wpas_rrm_process_msr_req_elems(struct wpa_supplicant *wpa_s, const u8 *pos,
+ size_t len)
+{
+ struct wpabuf *buf = NULL;
+
+ while (len) {
+ const struct rrm_measurement_request_element *req;
+ int res;
+
+ if (len < 2) {
+ wpa_printf(MSG_DEBUG, "RRM: Truncated element");
+ goto out;
+ }
+
+ req = (const struct rrm_measurement_request_element *) pos;
+ if (req->eid != WLAN_EID_MEASURE_REQUEST) {
+ wpa_printf(MSG_DEBUG,
+ "RRM: Expected Measurement Request element, but EID is %u",
+ req->eid);
+ goto out;
+ }
+
+ if (req->len < 3) {
+ wpa_printf(MSG_DEBUG, "RRM: Element length too short");
+ goto out;
+ }
+
+ if (req->len > len - 2) {
+ wpa_printf(MSG_DEBUG, "RRM: Element length too long");
+ goto out;
+ }
+
+ res = wpas_rrm_handle_msr_req_element(wpa_s, req, &buf);
+ if (res < 0)
+ goto out;
+
+ pos += req->len + 2;
+ len -= req->len + 2;
+ }
+
+ return buf;
+
+out:
+ wpabuf_free(buf);
+ return NULL;
+}
+
+
+void wpas_rrm_handle_radio_measurement_request(struct wpa_supplicant *wpa_s,
+ const u8 *src, const u8 *dst,
+ const u8 *frame, size_t len)
+{
+ struct wpabuf *report;
+
+ if (wpa_s->wpa_state != WPA_COMPLETED) {
+ wpa_printf(MSG_INFO,
+ "RRM: Ignoring radio measurement request: Not associated");
+ return;
+ }
+
+ if (!wpa_s->rrm.rrm_used) {
+ wpa_printf(MSG_INFO,
+ "RRM: Ignoring radio measurement request: Not RRM network");
+ return;
+ }
+
+ if (len < 3) {
+ wpa_printf(MSG_INFO,
+ "RRM: Ignoring too short radio measurement request");
+ return;
+ }
+
+ wpa_s->rrm.token = *frame;
+ os_memcpy(wpa_s->rrm.dst_addr, dst, ETH_ALEN);
+
+ /* Number of repetitions is not supported */
+
+ report = wpas_rrm_process_msr_req_elems(wpa_s, frame + 3, len - 3);
+ if (!report)
+ return;
+
+ wpas_rrm_send_msr_report(wpa_s, report);
+ wpabuf_free(report);
+}
+
+
+void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s,
+ const u8 *src,
+ const u8 *frame, size_t len,
+ int rssi)
+{
+ struct wpabuf *buf;
+ const struct rrm_link_measurement_request *req;
+ struct rrm_link_measurement_report report;
+
+ if (wpa_s->wpa_state != WPA_COMPLETED) {
+ wpa_printf(MSG_INFO,
+ "RRM: Ignoring link measurement request. Not associated");
+ return;
+ }
+
+ if (!wpa_s->rrm.rrm_used) {
+ wpa_printf(MSG_INFO,
+ "RRM: Ignoring link measurement request. Not RRM network");
+ return;
+ }
+
+ if (!(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)) {
+ wpa_printf(MSG_INFO,
+ "RRM: Measurement report failed. TX power insertion not supported");
+ return;
+ }
+
+ req = (const struct rrm_link_measurement_request *) frame;
+ if (len < sizeof(*req)) {
+ wpa_printf(MSG_INFO,
+ "RRM: Link measurement report failed. Request too short");
+ return;
+ }
+
+ os_memset(&report, 0, sizeof(report));
+ report.dialog_token = req->dialog_token;
+ report.tpc.eid = WLAN_EID_TPC_REPORT;
+ report.tpc.len = 2;
+ /* Note: The driver is expected to update report.tpc.tx_power and
+ * report.tpc.link_margin subfields when sending out this frame.
+ * Similarly, the driver would need to update report.rx_ant_id and
+ * report.tx_ant_id subfields. */
+ report.rsni = 255; /* 255 indicates that RSNI is not available */
+ report.rcpi = rssi_to_rcpi(rssi);
+
+ /* action_category + action_code */
+ buf = wpabuf_alloc(2 + sizeof(report));
+ if (buf == NULL) {
+ wpa_printf(MSG_ERROR,
+ "RRM: Link measurement report failed. Buffer allocation failed");
+ return;
+ }
+
+ wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
+ wpabuf_put_u8(buf, WLAN_RRM_LINK_MEASUREMENT_REPORT);
+ wpabuf_put_data(buf, &report, sizeof(report));
+ wpa_hexdump_buf(MSG_DEBUG, "RRM: Link measurement report", buf);
+
+ if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src,
+ wpa_s->own_addr, wpa_s->bssid,
+ wpabuf_head(buf), wpabuf_len(buf), 0)) {
+ wpa_printf(MSG_ERROR,
+ "RRM: Link measurement report failed. Send action failed");
+ }
+ wpabuf_free(buf);
+}
+
+
+int wpas_beacon_rep_scan_process(struct wpa_supplicant *wpa_s,
+ struct wpa_scan_results *scan_res,
+ struct scan_info *info)
+{
+ size_t i = 0;
+ struct wpabuf *buf = NULL;
+
+ if (!wpa_s->beacon_rep_data.token)
+ return 0;
+
+ if (!wpa_s->current_bss)
+ goto out;
+
+ /* If the measurement was aborted, don't report partial results */
+ if (info->aborted)
+ goto out;
+
+ wpa_printf(MSG_DEBUG, "RRM: TSF BSSID: " MACSTR " current BSS: " MACSTR,
+ MAC2STR(info->scan_start_tsf_bssid),
+ MAC2STR(wpa_s->current_bss->bssid));
+ if ((wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_SUPPORT_BEACON_REPORT) &&
+ os_memcmp(info->scan_start_tsf_bssid, wpa_s->current_bss->bssid,
+ ETH_ALEN) != 0) {
+ wpa_printf(MSG_DEBUG,
+ "RRM: Ignore scan results due to mismatching TSF BSSID");
+ goto out;
+ }
+
+ for (i = 0; i < scan_res->num; i++) {
+ struct wpa_bss *bss =
+ wpa_bss_get_bssid(wpa_s, scan_res->res[i]->bssid);
+
+ if (!bss)
+ continue;
+
+ if ((wpa_s->drv_rrm_flags &
+ WPA_DRIVER_FLAGS_SUPPORT_BEACON_REPORT) &&
+ os_memcmp(scan_res->res[i]->tsf_bssid,
+ wpa_s->current_bss->bssid, ETH_ALEN) != 0) {
+ wpa_printf(MSG_DEBUG,
+ "RRM: Ignore scan result for " MACSTR
+ " due to mismatching TSF BSSID" MACSTR,
+ MAC2STR(scan_res->res[i]->bssid),
+ MAC2STR(scan_res->res[i]->tsf_bssid));
+ continue;
+ }
+
+ /*
+ * Don't report results that were not received during the
+ * current measurement.
+ */
+ if (!(wpa_s->drv_rrm_flags &
+ WPA_DRIVER_FLAGS_SUPPORT_BEACON_REPORT)) {
+ struct os_reltime update_time, diff;
+
+ /* For now, allow 8 ms older results due to some
+ * unknown issue with cfg80211 BSS table updates during
+ * a scan with the current BSS.
+ * TODO: Fix this more properly to avoid having to have
+ * this type of hacks in place. */
+ calculate_update_time(&scan_res->fetch_time,
+ scan_res->res[i]->age,
+ &update_time);
+ os_reltime_sub(&wpa_s->beacon_rep_scan,
+ &update_time, &diff);
+ if (os_reltime_before(&update_time,
+ &wpa_s->beacon_rep_scan) &&
+ (diff.sec || diff.usec >= 8000)) {
+ wpa_printf(MSG_DEBUG,
+ "RRM: Ignore scan result for " MACSTR
+ " due to old update (age(ms) %u, calculated age %u.%06u seconds)",
+ MAC2STR(scan_res->res[i]->bssid),
+ scan_res->res[i]->age,
+ (unsigned int) diff.sec,
+ (unsigned int) diff.usec);
+ continue;
+ }
+ } else if (info->scan_start_tsf >
+ scan_res->res[i]->parent_tsf) {
+ continue;
+ }
+
+ if (wpas_add_beacon_rep(wpa_s, &buf, bss, info->scan_start_tsf,
+ scan_res->res[i]->parent_tsf) < 0)
+ break;
+ }
+
+ if (!buf && wpas_beacon_rep_no_results(wpa_s, &buf))
+ goto out;
+
+ wpa_hexdump_buf(MSG_DEBUG, "RRM: Radio Measurement report", buf);
+
+ wpas_rrm_send_msr_report(wpa_s, buf);
+ wpabuf_free(buf);
+
+out:
+ wpas_clear_beacon_rep_data(wpa_s);
+ return 1;
+}
+
+
+void wpas_clear_beacon_rep_data(struct wpa_supplicant *wpa_s)
+{
+ struct beacon_rep_data *data = &wpa_s->beacon_rep_data;
+
+ eloop_cancel_timeout(wpas_rrm_scan_timeout, wpa_s, NULL);
+ bitfield_free(data->eids);
+ os_free(data->scan_params.freqs);
+ os_memset(data, 0, sizeof(*data));
+}
diff --git a/freebsd/contrib/wpa/wpa_supplicant/scan.c b/freebsd/contrib/wpa/wpa_supplicant/scan.c
index 4fd269a8..41f95fb8 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/scan.c
+++ b/freebsd/contrib/wpa/wpa_supplicant/scan.c
@@ -2,7 +2,7 @@
/*
* WPA Supplicant - Scanning
- * Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -119,9 +119,19 @@ int wpa_supplicant_enabled_networks(struct wpa_supplicant *wpa_s)
static void wpa_supplicant_assoc_try(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid)
{
+ int min_temp_disabled = 0;
+
while (ssid) {
- if (!wpas_network_disabled(wpa_s, ssid))
- break;
+ if (!wpas_network_disabled(wpa_s, ssid)) {
+ int temp_disabled = wpas_temp_disabled(wpa_s, ssid);
+
+ if (temp_disabled <= 0)
+ break;
+
+ if (!min_temp_disabled ||
+ temp_disabled < min_temp_disabled)
+ min_temp_disabled = temp_disabled;
+ }
ssid = ssid->next;
}
@@ -130,7 +140,7 @@ static void wpa_supplicant_assoc_try(struct wpa_supplicant *wpa_s,
wpa_dbg(wpa_s, MSG_DEBUG, "wpa_supplicant_assoc_try: Reached "
"end of scan list - go back to beginning");
wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
- wpa_supplicant_req_scan(wpa_s, 0, 0);
+ wpa_supplicant_req_scan(wpa_s, min_temp_disabled, 0);
return;
}
if (ssid->next) {
@@ -178,10 +188,22 @@ static void wpas_trigger_scan_cb(struct wpa_radio_work *work, int deinit)
params->only_new_results = 1;
}
ret = wpa_drv_scan(wpa_s, params);
+ /*
+ * Store the obtained vendor scan cookie (if any) in wpa_s context.
+ * The current design is to allow only one scan request on each
+ * interface, hence having this scan cookie stored in wpa_s context is
+ * fine for now.
+ *
+ * Revisit this logic if concurrent scan operations per interface
+ * is supported.
+ */
+ if (ret == 0)
+ wpa_s->curr_scan_cookie = params->scan_cookie;
wpa_scan_free_params(params);
work->ctx = NULL;
if (ret) {
- int retry = wpa_s->last_scan_req != MANUAL_SCAN_REQ;
+ int retry = wpa_s->last_scan_req != MANUAL_SCAN_REQ &&
+ !wpa_s->beacon_rep_data.token;
if (wpa_s->disconnected)
retry = 0;
@@ -199,7 +221,14 @@ static void wpas_trigger_scan_cb(struct wpa_radio_work *work, int deinit)
/* Restore scan_req since we will try to scan again */
wpa_s->scan_req = wpa_s->last_scan_req;
wpa_supplicant_req_scan(wpa_s, 1, 0);
+ } else if (wpa_s->scan_res_handler) {
+ /* Clear the scan_res_handler */
+ wpa_s->scan_res_handler = NULL;
}
+
+ if (wpa_s->beacon_rep_data.token)
+ wpas_rrm_refuse_request(wpa_s);
+
return;
}
@@ -428,6 +457,33 @@ static void wpas_add_interworking_elements(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_INTERWORKING */
+#ifdef CONFIG_MBO
+static void wpas_fils_req_param_add_max_channel(struct wpa_supplicant *wpa_s,
+ struct wpabuf **ie)
+{
+ if (wpabuf_resize(ie, 5)) {
+ wpa_printf(MSG_DEBUG,
+ "Failed to allocate space for FILS Request Parameters element");
+ return;
+ }
+
+ /* FILS Request Parameters element */
+ wpabuf_put_u8(*ie, WLAN_EID_EXTENSION);
+ wpabuf_put_u8(*ie, 3); /* FILS Request attribute length */
+ wpabuf_put_u8(*ie, WLAN_EID_EXT_FILS_REQ_PARAMS);
+ /* Parameter control bitmap */
+ wpabuf_put_u8(*ie, 0);
+ /* Max Channel Time field - contains the value of MaxChannelTime
+ * parameter of the MLME-SCAN.request primitive represented in units of
+ * TUs, as an unsigned integer. A Max Channel Time field value of 255
+ * is used to indicate any duration of more than 254 TUs, or an
+ * unspecified or unknown duration. (IEEE Std 802.11ai-2016, 9.4.2.178)
+ */
+ wpabuf_put_u8(*ie, 255);
+}
+#endif /* CONFIG_MBO */
+
+
void wpa_supplicant_set_default_scan_ies(struct wpa_supplicant *wpa_s)
{
struct wpabuf *default_ies = NULL;
@@ -449,8 +505,10 @@ void wpa_supplicant_set_default_scan_ies(struct wpa_supplicant *wpa_s)
wpabuf_put_data(default_ies, ext_capab, ext_capab_len);
#ifdef CONFIG_MBO
- /* Send cellular capabilities for potential MBO STAs */
- if (wpabuf_resize(&default_ies, 9) == 0)
+ if (wpa_s->enable_oce & OCE_STA)
+ wpas_fils_req_param_add_max_channel(wpa_s, &default_ies);
+ /* Send MBO and OCE capabilities */
+ if (wpabuf_resize(&default_ies, 12) == 0)
wpas_mbo_scan_ie(wpa_s, default_ies);
#endif /* CONFIG_MBO */
@@ -490,6 +548,11 @@ static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s)
wpas_add_interworking_elements(wpa_s, extra_ie);
#endif /* CONFIG_INTERWORKING */
+#ifdef CONFIG_MBO
+ if (wpa_s->enable_oce & OCE_STA)
+ wpas_fils_req_param_add_max_channel(wpa_s, &extra_ie);
+#endif /* CONFIG_MBO */
+
#ifdef CONFIG_WPS
wps = wpas_wps_in_use(wpa_s, &req_type);
@@ -520,8 +583,8 @@ static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s)
#endif /* CONFIG_WPS */
#ifdef CONFIG_HS20
- if (wpa_s->conf->hs20 && wpabuf_resize(&extra_ie, 7) == 0)
- wpas_hs20_add_indication(extra_ie, -1);
+ if (wpa_s->conf->hs20 && wpabuf_resize(&extra_ie, 9) == 0)
+ wpas_hs20_add_indication(extra_ie, -1, 0);
#endif /* CONFIG_HS20 */
#ifdef CONFIG_FST
@@ -531,8 +594,8 @@ static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s)
#endif /* CONFIG_FST */
#ifdef CONFIG_MBO
- /* Send cellular capabilities for potential MBO STAs */
- if (wpabuf_resize(&extra_ie, 9) == 0)
+ /* Send MBO and OCE capabilities */
+ if (wpabuf_resize(&extra_ie, 12) == 0)
wpas_mbo_scan_ie(wpa_s, extra_ie);
#endif /* CONFIG_MBO */
@@ -616,6 +679,87 @@ static void wpa_setband_scan_freqs(struct wpa_supplicant *wpa_s,
}
+static void wpa_add_scan_ssid(struct wpa_supplicant *wpa_s,
+ struct wpa_driver_scan_params *params,
+ size_t max_ssids, const u8 *ssid, size_t ssid_len)
+{
+ unsigned int j;
+
+ for (j = 0; j < params->num_ssids; j++) {
+ if (params->ssids[j].ssid_len == ssid_len &&
+ params->ssids[j].ssid &&
+ os_memcmp(params->ssids[j].ssid, ssid, ssid_len) == 0)
+ return; /* already in the list */
+ }
+
+ if (params->num_ssids + 1 > max_ssids) {
+ wpa_printf(MSG_DEBUG, "Over max scan SSIDs for manual request");
+ return;
+ }
+
+ wpa_printf(MSG_DEBUG, "Scan SSID (manual request): %s",
+ wpa_ssid_txt(ssid, ssid_len));
+
+ params->ssids[params->num_ssids].ssid = ssid;
+ params->ssids[params->num_ssids].ssid_len = ssid_len;
+ params->num_ssids++;
+}
+
+
+static void wpa_add_owe_scan_ssid(struct wpa_supplicant *wpa_s,
+ struct wpa_driver_scan_params *params,
+ struct wpa_ssid *ssid, size_t max_ssids)
+{
+#ifdef CONFIG_OWE
+ struct wpa_bss *bss;
+
+ if (!(ssid->key_mgmt & WPA_KEY_MGMT_OWE))
+ return;
+
+ wpa_printf(MSG_DEBUG, "OWE: Look for transition mode AP. ssid=%s",
+ wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
+
+ dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
+ const u8 *owe, *pos, *end;
+ const u8 *owe_ssid;
+ size_t owe_ssid_len;
+
+ if (bss->ssid_len != ssid->ssid_len ||
+ os_memcmp(bss->ssid, ssid->ssid, ssid->ssid_len) != 0)
+ continue;
+
+ owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
+ if (!owe || owe[1] < 4)
+ continue;
+
+ pos = owe + 6;
+ end = owe + 2 + owe[1];
+
+ /* Must include BSSID and ssid_len */
+ if (end - pos < ETH_ALEN + 1)
+ return;
+
+ /* Skip BSSID */
+ pos += ETH_ALEN;
+ owe_ssid_len = *pos++;
+ owe_ssid = pos;
+
+ if ((size_t) (end - pos) < owe_ssid_len ||
+ owe_ssid_len > SSID_MAX_LEN)
+ return;
+
+ wpa_printf(MSG_DEBUG,
+ "OWE: scan_ssids: transition mode OWE ssid=%s",
+ wpa_ssid_txt(owe_ssid, owe_ssid_len));
+
+ wpa_add_scan_ssid(wpa_s, params, max_ssids,
+ owe_ssid, owe_ssid_len);
+ return;
+ }
+#endif /* CONFIG_OWE */
+}
+
+
static void wpa_set_scan_ssids(struct wpa_supplicant *wpa_s,
struct wpa_driver_scan_params *params,
size_t max_ssids)
@@ -630,33 +774,17 @@ static void wpa_set_scan_ssids(struct wpa_supplicant *wpa_s,
max_ssids = max_ssids > 1 ? max_ssids - 1 : max_ssids;
for (i = 0; i < wpa_s->scan_id_count; i++) {
- unsigned int j;
-
ssid = wpa_config_get_network(wpa_s->conf, wpa_s->scan_id[i]);
- if (!ssid || !ssid->scan_ssid)
+ if (!ssid)
continue;
-
- for (j = 0; j < params->num_ssids; j++) {
- if (params->ssids[j].ssid_len == ssid->ssid_len &&
- params->ssids[j].ssid &&
- os_memcmp(params->ssids[j].ssid, ssid->ssid,
- ssid->ssid_len) == 0)
- break;
- }
- if (j < params->num_ssids)
- continue; /* already in the list */
-
- if (params->num_ssids + 1 > max_ssids) {
- wpa_printf(MSG_DEBUG,
- "Over max scan SSIDs for manual request");
- break;
- }
-
- wpa_printf(MSG_DEBUG, "Scan SSID (manual request): %s",
- wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
- params->ssids[params->num_ssids].ssid = ssid->ssid;
- params->ssids[params->num_ssids].ssid_len = ssid->ssid_len;
- params->num_ssids++;
+ if (ssid->scan_ssid)
+ wpa_add_scan_ssid(wpa_s, params, max_ssids,
+ ssid->ssid, ssid->ssid_len);
+ /*
+ * Also add the SSID of the OWE BSS, to allow discovery of
+ * transition mode APs more quickly.
+ */
+ wpa_add_owe_scan_ssid(wpa_s, params, ssid, max_ssids);
}
wpa_s->scan_id_count = 0;
@@ -705,10 +833,7 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
size_t max_ssids;
int connect_without_scan = 0;
- if (wpa_s->pno || wpa_s->pno_sched_pending) {
- wpa_dbg(wpa_s, MSG_DEBUG, "Skip scan - PNO is in progress");
- return;
- }
+ wpa_s->ignore_post_flush_scan_res = 0;
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
wpa_dbg(wpa_s, MSG_DEBUG, "Skip scan - interface disabled");
@@ -770,6 +895,21 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
return;
}
+ /*
+ * Don't cancel the scan based on ongoing PNO; defer it. Some scans are
+ * used for changing modes inside wpa_supplicant (roaming,
+ * auto-reconnect, etc). Discarding the scan might hurt these processes.
+ * The normal use case for PNO is to suspend the host immediately after
+ * starting PNO, so the periodic 100 ms attempts to run the scan do not
+ * normally happen in practice multiple times, i.e., this is simply
+ * restarting scanning once the host is woken up and PNO stopped.
+ */
+ if (wpa_s->pno || wpa_s->pno_sched_pending) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "Defer scan - PNO is in progress");
+ wpa_supplicant_req_scan(wpa_s, 0, 100000);
+ return;
+ }
+
if (wpa_s->conf->ap_scan == 2)
max_ssids = 1;
else {
@@ -911,6 +1051,17 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
if (params.num_ssids + 1 >= max_ssids)
break;
}
+
+ if (!wpas_network_disabled(wpa_s, ssid)) {
+ /*
+ * Also add the SSID of the OWE BSS, to allow
+ * discovery of transition mode APs more
+ * quickly.
+ */
+ wpa_add_owe_scan_ssid(wpa_s, &params, ssid,
+ max_ssids);
+ }
+
ssid = ssid->next;
if (ssid == start)
break;
@@ -997,6 +1148,13 @@ ssid_list_set:
wpa_s->manual_scan_freqs = NULL;
}
+ if (params.freqs == NULL && wpa_s->select_network_scan_freqs) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Limit select_network scan to specified channels");
+ params.freqs = wpa_s->select_network_scan_freqs;
+ wpa_s->select_network_scan_freqs = NULL;
+ }
+
if (params.freqs == NULL && wpa_s->next_scan_freqs) {
wpa_dbg(wpa_s, MSG_DEBUG, "Optimize scan based on previously "
"generated frequency list");
@@ -1031,6 +1189,11 @@ ssid_list_set:
}
}
+#ifdef CONFIG_MBO
+ if (wpa_s->enable_oce & OCE_STA)
+ params.oce_scan = 1;
+#endif /* CONFIG_MBO */
+
params.filter_ssids = wpa_supplicant_build_filter_ssids(
wpa_s->conf, &params.num_filter_ssids);
if (extra_ie) {
@@ -1049,7 +1212,8 @@ ssid_list_set:
}
#endif /* CONFIG_P2P */
- if (wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_SCAN) {
+ if ((wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_SCAN) &&
+ wpa_s->wpa_state <= WPA_SCANNING) {
params.mac_addr_rand = 1;
if (wpa_s->mac_addr_scan) {
params.mac_addr = wpa_s->mac_addr_scan;
@@ -1227,6 +1391,26 @@ int wpa_supplicant_delayed_sched_scan(struct wpa_supplicant *wpa_s,
}
+static void
+wpa_scan_set_relative_rssi_params(struct wpa_supplicant *wpa_s,
+ struct wpa_driver_scan_params *params)
+{
+ if (wpa_s->wpa_state != WPA_COMPLETED ||
+ !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SCHED_SCAN_RELATIVE_RSSI) ||
+ wpa_s->srp.relative_rssi_set == 0)
+ return;
+
+ params->relative_rssi_set = 1;
+ params->relative_rssi = wpa_s->srp.relative_rssi;
+
+ if (wpa_s->srp.relative_adjust_rssi == 0)
+ return;
+
+ params->relative_adjust_band = wpa_s->srp.relative_adjust_band;
+ params->relative_adjust_rssi = wpa_s->srp.relative_adjust_rssi;
+}
+
+
/**
* wpa_supplicant_req_sched_scan - Start a periodic scheduled scan
* @wpa_s: Pointer to wpa_supplicant data
@@ -1419,6 +1603,11 @@ int wpa_supplicant_req_sched_scan(struct wpa_supplicant *wpa_s)
int_array_concat(&params.freqs, wpa_s->conf->freq_list);
}
+#ifdef CONFIG_MBO
+ if (wpa_s->enable_oce & OCE_STA)
+ params.oce_scan = 1;
+#endif /* CONFIG_MBO */
+
scan_params = &params;
scan:
@@ -1460,18 +1649,24 @@ scan:
params.sched_scan_plans_num = 1;
}
+ params.sched_scan_start_delay = wpa_s->conf->sched_scan_start_delay;
+
if (ssid || !wpa_s->first_sched_scan) {
wpa_dbg(wpa_s, MSG_DEBUG,
- "Starting sched scan: interval %u timeout %d",
+ "Starting sched scan after %u seconds: interval %u timeout %d",
+ params.sched_scan_start_delay,
params.sched_scan_plans[0].interval,
wpa_s->sched_scan_timeout);
} else {
- wpa_dbg(wpa_s, MSG_DEBUG, "Starting sched scan (no timeout)");
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Starting sched scan after %u seconds (no timeout)",
+ params.sched_scan_start_delay);
}
wpa_setband_scan_freqs(wpa_s, scan_params);
- if (wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_SCHED_SCAN) {
+ if ((wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_SCHED_SCAN) &&
+ wpa_s->wpa_state <= WPA_SCANNING) {
params.mac_addr_rand = 1;
if (wpa_s->mac_addr_sched_scan) {
params.mac_addr = wpa_s->mac_addr_sched_scan;
@@ -1480,6 +1675,8 @@ scan:
}
}
+ wpa_scan_set_relative_rssi_params(wpa_s, scan_params);
+
ret = wpa_supplicant_start_sched_scan(wpa_s, scan_params);
wpabuf_free(extra_ie);
os_free(params.filter_ssids);
@@ -1620,7 +1817,13 @@ static int wpa_scan_get_max_rate(const struct wpa_scan_res *res)
*/
const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie)
{
- return get_ie((const u8 *) (res + 1), res->ie_len, ie);
+ size_t ie_len = res->ie_len;
+
+ /* Use the Beacon frame IEs if res->ie_len is not available */
+ if (!ie_len)
+ ie_len = res->beacon_ie_len;
+
+ return get_ie((const u8 *) (res + 1), ie_len, ie);
}
@@ -1737,10 +1940,12 @@ struct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res,
* This doc https://supportforums.cisco.com/docs/DOC-12954 says, "the general
* rule of thumb is that any SNR above 20 is good." This one
* http://www.cisco.com/en/US/tech/tk722/tk809/technologies_q_and_a_item09186a00805e9a96.shtml#qa23
- * recommends 25 as a minimum SNR for 54 Mbps data rate. 30 is chosen here as a
- * conservative value.
+ * recommends 25 as a minimum SNR for 54 Mbps data rate. The estimates used in
+ * scan_est_throughput() allow even smaller SNR values for the maximum rates
+ * (21 for 54 Mbps, 22 for VHT80 MCS9, 24 for HT40 and HT20 MCS7). Use 25 as a
+ * somewhat conservative value here.
*/
-#define GREAT_SNR 30
+#define GREAT_SNR 25
#define IS_5GHZ(n) (n > 4000)
@@ -1788,10 +1993,13 @@ static int wpa_scan_result_compar(const void *a, const void *b)
}
/* if SNR is close, decide by max rate or frequency band */
+ if (snr_a && snr_b && abs(snr_b - snr_a) < 7) {
+ if (wa->est_throughput != wb->est_throughput)
+ return (int) wb->est_throughput -
+ (int) wa->est_throughput;
+ }
if ((snr_a && snr_b && abs(snr_b - snr_a) < 5) ||
(wa->qual && wb->qual && abs(wb->qual - wa->qual) < 10)) {
- if (wa->est_throughput != wb->est_throughput)
- return wb->est_throughput - wa->est_throughput;
if (IS_5GHZ(wa->freq) ^ IS_5GHZ(wb->freq))
return IS_5GHZ(wa->freq) ? -1 : 1;
}
@@ -2179,10 +2387,22 @@ wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s,
}
#endif /* CONFIG_WPS */
- qsort(scan_res->res, scan_res->num, sizeof(struct wpa_scan_res *),
- compar);
+ if (scan_res->res) {
+ qsort(scan_res->res, scan_res->num,
+ sizeof(struct wpa_scan_res *), compar);
+ }
dump_scan_res(scan_res);
+ if (wpa_s->ignore_post_flush_scan_res) {
+ /* FLUSH command aborted an ongoing scan and these are the
+ * results from the aborted scan. Do not process the results to
+ * maintain flushed state. */
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Do not update BSS table based on pending post-FLUSH scan results");
+ wpa_s->ignore_post_flush_scan_res = 0;
+ return scan_res;
+ }
+
wpa_bss_update_start(wpa_s);
for (i = 0; i < scan_res->num; i++)
wpa_bss_update_scan_res(wpa_s, scan_res->res[i],
@@ -2264,11 +2484,10 @@ wpa_scan_clone_params(const struct wpa_driver_scan_params *src)
for (i = 0; i < src->num_ssids; i++) {
if (src->ssids[i].ssid) {
- n = os_malloc(src->ssids[i].ssid_len);
+ n = os_memdup(src->ssids[i].ssid,
+ src->ssids[i].ssid_len);
if (n == NULL)
goto failed;
- os_memcpy(n, src->ssids[i].ssid,
- src->ssids[i].ssid_len);
params->ssids[i].ssid = n;
params->ssids[i].ssid_len = src->ssids[i].ssid_len;
}
@@ -2276,30 +2495,26 @@ wpa_scan_clone_params(const struct wpa_driver_scan_params *src)
params->num_ssids = src->num_ssids;
if (src->extra_ies) {
- n = os_malloc(src->extra_ies_len);
+ n = os_memdup(src->extra_ies, src->extra_ies_len);
if (n == NULL)
goto failed;
- os_memcpy(n, src->extra_ies, src->extra_ies_len);
params->extra_ies = n;
params->extra_ies_len = src->extra_ies_len;
}
if (src->freqs) {
int len = int_array_len(src->freqs);
- params->freqs = os_malloc((len + 1) * sizeof(int));
+ params->freqs = os_memdup(src->freqs, (len + 1) * sizeof(int));
if (params->freqs == NULL)
goto failed;
- os_memcpy(params->freqs, src->freqs, (len + 1) * sizeof(int));
}
if (src->filter_ssids) {
- params->filter_ssids = os_malloc(sizeof(*params->filter_ssids) *
+ params->filter_ssids = os_memdup(src->filter_ssids,
+ sizeof(*params->filter_ssids) *
src->num_filter_ssids);
if (params->filter_ssids == NULL)
goto failed;
- os_memcpy(params->filter_ssids, src->filter_ssids,
- sizeof(*params->filter_ssids) *
- src->num_filter_ssids);
params->num_filter_ssids = src->num_filter_ssids;
}
@@ -2307,17 +2522,18 @@ wpa_scan_clone_params(const struct wpa_driver_scan_params *src)
params->p2p_probe = src->p2p_probe;
params->only_new_results = src->only_new_results;
params->low_priority = src->low_priority;
+ params->duration = src->duration;
+ params->duration_mandatory = src->duration_mandatory;
+ params->oce_scan = src->oce_scan;
if (src->sched_scan_plans_num > 0) {
params->sched_scan_plans =
- os_malloc(sizeof(*src->sched_scan_plans) *
+ os_memdup(src->sched_scan_plans,
+ sizeof(*src->sched_scan_plans) *
src->sched_scan_plans_num);
if (!params->sched_scan_plans)
goto failed;
- os_memcpy(params->sched_scan_plans, src->sched_scan_plans,
- sizeof(*src->sched_scan_plans) *
- src->sched_scan_plans_num);
params->sched_scan_plans_num = src->sched_scan_plans_num;
}
@@ -2342,13 +2558,16 @@ wpa_scan_clone_params(const struct wpa_driver_scan_params *src)
if (src->bssid) {
u8 *bssid;
- bssid = os_malloc(ETH_ALEN);
+ bssid = os_memdup(src->bssid, ETH_ALEN);
if (!bssid)
goto failed;
- os_memcpy(bssid, src->bssid, ETH_ALEN);
params->bssid = bssid;
}
+ params->relative_rssi_set = src->relative_rssi_set;
+ params->relative_rssi = src->relative_rssi;
+ params->relative_adjust_band = src->relative_adjust_band;
+ params->relative_adjust_rssi = src->relative_adjust_rssi;
return params;
failed:
@@ -2406,7 +2625,7 @@ int wpas_start_pno(struct wpa_supplicant *wpa_s)
return 0;
if ((wpa_s->wpa_state > WPA_SCANNING) &&
- (wpa_s->wpa_state <= WPA_COMPLETED)) {
+ (wpa_s->wpa_state < WPA_COMPLETED)) {
wpa_printf(MSG_ERROR, "PNO: In assoc process");
return -EAGAIN;
}
@@ -2513,12 +2732,15 @@ int wpas_start_pno(struct wpa_supplicant *wpa_s)
params.sched_scan_plans_num = 1;
}
+ params.sched_scan_start_delay = wpa_s->conf->sched_scan_start_delay;
+
if (params.freqs == NULL && wpa_s->manual_sched_scan_freqs) {
wpa_dbg(wpa_s, MSG_DEBUG, "Limit sched scan to specified channels");
params.freqs = wpa_s->manual_sched_scan_freqs;
}
- if (wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_PNO) {
+ if ((wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_PNO) &&
+ wpa_s->wpa_state <= WPA_SCANNING) {
params.mac_addr_rand = 1;
if (wpa_s->mac_addr_pno) {
params.mac_addr = wpa_s->mac_addr_pno;
@@ -2526,6 +2748,8 @@ int wpas_start_pno(struct wpa_supplicant *wpa_s)
}
}
+ wpa_scan_set_relative_rssi_params(wpa_s, &params);
+
ret = wpa_supplicant_start_sched_scan(wpa_s, &params);
os_free(params.filter_ssids);
if (ret == 0)
@@ -2585,6 +2809,13 @@ int wpas_mac_addr_rand_scan_set(struct wpa_supplicant *wpa_s,
{
u8 *tmp = NULL;
+ if ((wpa_s->mac_addr_rand_supported & type) != type ) {
+ wpa_printf(MSG_INFO,
+ "scan: MAC randomization type %u != supported=%u",
+ type, wpa_s->mac_addr_rand_supported);
+ return -1;
+ }
+
wpas_mac_addr_rand_scan_clear(wpa_s, type);
if (addr) {
@@ -2616,18 +2847,20 @@ int wpas_mac_addr_rand_scan_set(struct wpa_supplicant *wpa_s,
int wpas_abort_ongoing_scan(struct wpa_supplicant *wpa_s)
{
- int scan_work = !!wpa_s->scan_work;
-
-#ifdef CONFIG_P2P
- scan_work |= !!wpa_s->p2p_scan_work;
-#endif /* CONFIG_P2P */
+ struct wpa_radio_work *work;
+ struct wpa_radio *radio = wpa_s->radio;
- if (scan_work && wpa_s->own_scan_running) {
+ dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
+ if (work->wpa_s != wpa_s || !work->started ||
+ (os_strcmp(work->type, "scan") != 0 &&
+ os_strcmp(work->type, "p2p-scan") != 0))
+ continue;
wpa_dbg(wpa_s, MSG_DEBUG, "Abort an ongoing scan");
- return wpa_drv_abort_scan(wpa_s);
+ return wpa_drv_abort_scan(wpa_s, wpa_s->curr_scan_cookie);
}
- return 0;
+ wpa_dbg(wpa_s, MSG_DEBUG, "No ongoing scan/p2p-scan found to abort");
+ return -1;
}
diff --git a/freebsd/contrib/wpa/wpa_supplicant/sme.h b/freebsd/contrib/wpa/wpa_supplicant/sme.h
index fd5c3b4e..1a7f9e83 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/sme.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/sme.h
@@ -28,6 +28,7 @@ void sme_event_disassoc(struct wpa_supplicant *wpa_s,
struct disassoc_info *info);
void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s, const u8 *sa,
const u8 *da, u16 reason_code);
+void sme_event_ch_switch(struct wpa_supplicant *wpa_s);
void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *sa,
const u8 *data, size_t len);
void sme_state_changed(struct wpa_supplicant *wpa_s);
@@ -38,6 +39,10 @@ void sme_deinit(struct wpa_supplicant *wpa_s);
int sme_proc_obss_scan(struct wpa_supplicant *wpa_s);
void sme_sched_obss_scan(struct wpa_supplicant *wpa_s, int enable);
+void sme_external_auth_trigger(struct wpa_supplicant *wpa_s,
+ union wpa_event_data *data);
+void sme_external_auth_mgmt_rx(struct wpa_supplicant *wpa_s,
+ const u8 *auth_frame, size_t len);
#else /* CONFIG_SME */
@@ -85,6 +90,10 @@ static inline void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s,
{
}
+static inline void sme_event_ch_switch(struct wpa_supplicant *wpa_s)
+{
+}
+
static inline void sme_state_changed(struct wpa_supplicant *wpa_s)
{
}
@@ -113,6 +122,16 @@ static inline void sme_sched_obss_scan(struct wpa_supplicant *wpa_s,
{
}
+static inline void sme_external_auth_trigger(struct wpa_supplicant *wpa_s,
+ union wpa_event_data *data)
+{
+}
+
+static inline void sme_external_auth_mgmt_rx(struct wpa_supplicant *wpa_s,
+ const u8 *auth_frame, size_t len)
+{
+}
+
#endif /* CONFIG_SME */
#endif /* SME_H */
diff --git a/freebsd/contrib/wpa/wpa_supplicant/wmm_ac.c b/freebsd/contrib/wpa/wpa_supplicant/wmm_ac.c
index 4d7b064b..b1a18748 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/wmm_ac.c
+++ b/freebsd/contrib/wpa/wpa_supplicant/wmm_ac.c
@@ -89,13 +89,10 @@ static int wmm_ac_add_ts(struct wpa_supplicant *wpa_s, const u8 *addr,
}
/* copy tspec */
- _tspec = os_malloc(sizeof(*_tspec));
+ _tspec = os_memdup(tspec, sizeof(*_tspec));
if (!_tspec)
return -1;
- /* store the admitted TSPEC */
- os_memcpy(_tspec, tspec, sizeof(*_tspec));
-
if (dir != WMM_AC_DIR_DOWNLINK) {
ret = wpa_drv_add_ts(wpa_s, tsid, addr, up, admitted_time);
wpa_printf(MSG_DEBUG,
@@ -476,13 +473,8 @@ static int wmm_ac_init(struct wpa_supplicant *wpa_s, const u8 *ies,
return -1;
}
- if (!ies) {
- wpa_printf(MSG_ERROR, "WMM AC: Missing IEs");
- return -1;
- }
-
- if (!(wmm_params->info_bitmap & WMM_PARAMS_UAPSD_QUEUES_INFO)) {
- wpa_printf(MSG_DEBUG, "WMM AC: Missing U-APSD configuration");
+ if (!ies || !(wmm_params->info_bitmap & WMM_PARAMS_UAPSD_QUEUES_INFO)) {
+ /* WMM AC not in use for this connection */
return -1;
}
@@ -527,7 +519,7 @@ static void wmm_ac_deinit(struct wpa_supplicant *wpa_s)
for (i = 0; i < WMM_AC_NUM; i++)
wmm_ac_del_ts(wpa_s, i, TS_DIR_IDX_ALL);
- /* delete pending add_ts requset */
+ /* delete pending add_ts request */
wmm_ac_del_req(wpa_s, 1);
os_free(wpa_s->wmm_ac_assoc_info);
diff --git a/freebsd/contrib/wpa/wpa_supplicant/wnm_sta.h b/freebsd/contrib/wpa/wpa_supplicant/wnm_sta.h
index 81d81535..29625f8c 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/wnm_sta.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/wnm_sta.h
@@ -43,6 +43,10 @@ struct neighbor_report {
unsigned int rm_capab_present:1;
unsigned int bearing_present:1;
unsigned int bss_term_present:1;
+ unsigned int acceptable:1;
+#ifdef CONFIG_MBO
+ unsigned int is_first:1;
+#endif /* CONFIG_MBO */
struct measurement_pilot *meas_pilot;
struct multiple_bssid *mul_bssid;
int freq;
@@ -56,13 +60,21 @@ void ieee802_11_rx_wnm_action(struct wpa_supplicant *wpa_s,
const struct ieee80211_mgmt *mgmt, size_t len);
int wnm_send_bss_transition_mgmt_query(struct wpa_supplicant *wpa_s,
- u8 query_reason, int cand_list);
+ u8 query_reason,
+ const char *btm_candidates,
+ int cand_list);
+
void wnm_deallocate_memory(struct wpa_supplicant *wpa_s);
+int wnm_send_coloc_intf_report(struct wpa_supplicant *wpa_s, u8 dialog_token,
+ const struct wpabuf *elems);
+void wnm_set_coloc_intf_elems(struct wpa_supplicant *wpa_s,
+ struct wpabuf *elems);
#ifdef CONFIG_WNM
int wnm_scan_process(struct wpa_supplicant *wpa_s, int reply_on_fail);
+void wnm_clear_coloc_intf_reporting(struct wpa_supplicant *wpa_s);
#else /* CONFIG_WNM */
@@ -72,6 +84,10 @@ static inline int wnm_scan_process(struct wpa_supplicant *wpa_s,
return 0;
}
+static inline void wnm_clear_coloc_intf_reporting(struct wpa_supplicant *wpa_s)
+{
+}
+
#endif /* CONFIG_WNM */
#endif /* WNM_STA_H */
diff --git a/freebsd/contrib/wpa/wpa_supplicant/wpa_supplicant.c b/freebsd/contrib/wpa/wpa_supplicant/wpa_supplicant.c
index 7346ae0b..1bc62ce6 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/wpa_supplicant.c
+++ b/freebsd/contrib/wpa/wpa_supplicant/wpa_supplicant.c
@@ -2,7 +2,7 @@
/*
* WPA Supplicant
- * Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -40,6 +40,8 @@
#include "common/wpa_ctrl.h"
#include "common/ieee802_11_defs.h"
#include "common/hw_features_common.h"
+#include "common/gas_server.h"
+#include "common/dpp.h"
#include "p2p/p2p.h"
#include "fst/fst.h"
#include "blacklist.h"
@@ -61,10 +63,15 @@
#include "wnm_sta.h"
#include "wpas_kay.h"
#include "mesh.h"
+#include "dpp_supplicant.h"
+#ifdef CONFIG_MESH
+#include "ap/ap_config.h"
+#include "ap/hostapd.h"
+#endif /* CONFIG_MESH */
const char *const wpa_supplicant_version =
"wpa_supplicant v" VERSION_STR "\n"
-"Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi> and contributors";
+"Copyright (c) 2003-2019, Jouni Malinen <j@w1.fi> and contributors";
const char *const wpa_supplicant_license =
"This software may be distributed under the terms of the BSD license.\n"
@@ -114,6 +121,13 @@ const char *const wpa_supplicant_full_license5 =
"\n";
#endif /* CONFIG_NO_STDOUT_DEBUG */
+
+static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx);
+#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
+static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s);
+#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
+
+
/* Configure default/group WEP keys for static WEP */
int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
{
@@ -232,10 +246,30 @@ void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
"%d usec", sec, usec);
eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
+ wpa_s->last_auth_timeout_sec = sec;
eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
}
+/*
+ * wpas_auth_timeout_restart - Restart and change timeout for authentication
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @sec_diff: difference in seconds applied to original timeout value
+ */
+void wpas_auth_timeout_restart(struct wpa_supplicant *wpa_s, int sec_diff)
+{
+ int new_sec = wpa_s->last_auth_timeout_sec + sec_diff;
+
+ if (eloop_is_timeout_registered(wpa_supplicant_timeout, wpa_s, NULL)) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Authentication timeout restart: %d sec", new_sec);
+ eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
+ eloop_register_timeout(new_sec, 0, wpa_supplicant_timeout,
+ wpa_s, NULL);
+ }
+}
+
+
/**
* wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
* @wpa_s: Pointer to wpa_supplicant data
@@ -249,6 +283,9 @@ void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
wpa_blacklist_del(wpa_s, wpa_s->bssid);
+ os_free(wpa_s->last_con_fail_realm);
+ wpa_s->last_con_fail_realm = NULL;
+ wpa_s->last_con_fail_realm_len = 0;
}
@@ -331,7 +368,12 @@ void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
- ieee802_1x_alloc_kay_sm(wpa_s, ssid);
+#ifdef CONFIG_MACSEC
+ if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE && ssid->mka_psk_set)
+ ieee802_1x_create_preshared_mka(wpa_s, ssid);
+ else
+ ieee802_1x_alloc_kay_sm(wpa_s, ssid);
+#endif /* CONFIG_MACSEC */
#endif /* IEEE8021X_EAPOL */
}
@@ -405,18 +447,32 @@ void free_hw_features(struct wpa_supplicant *wpa_s)
}
-static void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
+void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
{
struct wpa_bss_tmp_disallowed *bss, *prev;
dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
struct wpa_bss_tmp_disallowed, list) {
+ eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
dl_list_del(&bss->list);
os_free(bss);
}
}
+void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s)
+{
+ struct fils_hlp_req *req;
+
+ while ((req = dl_list_first(&wpa_s->fils_hlp_req, struct fils_hlp_req,
+ list)) != NULL) {
+ dl_list_del(&req->list);
+ wpabuf_free(req->pkt);
+ os_free(req);
+ }
+}
+
+
static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
{
int i;
@@ -436,6 +492,10 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
#ifdef CONFIG_TESTING_OPTIONS
l2_packet_deinit(wpa_s->l2_test);
wpa_s->l2_test = NULL;
+ os_free(wpa_s->get_pref_freq_list_override);
+ wpa_s->get_pref_freq_list_override = NULL;
+ wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
+ wpa_s->last_assoc_req_wpa_ie = NULL;
#endif /* CONFIG_TESTING_OPTIONS */
if (wpa_s->conf != NULL) {
@@ -450,6 +510,10 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
os_free(wpa_s->confanother);
wpa_s->confanother = NULL;
+ os_free(wpa_s->last_con_fail_realm);
+ wpa_s->last_con_fail_realm = NULL;
+ wpa_s->last_con_fail_realm_len = 0;
+
wpa_sm_set_eapol(wpa_s->wpa, NULL);
eapol_sm_deinit(wpa_s->eapol);
wpa_s->eapol = NULL;
@@ -508,6 +572,8 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
os_free(wpa_s->manual_scan_freqs);
wpa_s->manual_scan_freqs = NULL;
+ os_free(wpa_s->select_network_scan_freqs);
+ wpa_s->select_network_scan_freqs = NULL;
os_free(wpa_s->manual_sched_scan_freqs);
wpa_s->manual_sched_scan_freqs = NULL;
@@ -526,6 +592,8 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
radio_remove_works(wpa_s, "gas-query", 0);
gas_query_deinit(wpa_s->gas);
wpa_s->gas = NULL;
+ gas_server_deinit(wpa_s->gas_server);
+ wpa_s->gas_server = NULL;
free_hw_features(wpa_s);
@@ -582,6 +650,34 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
wpabuf_free(wpa_s->lci);
wpa_s->lci = NULL;
+ wpas_clear_beacon_rep_data(wpa_s);
+
+#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
+#ifdef CONFIG_MESH
+ {
+ struct external_pmksa_cache *entry;
+
+ while ((entry = dl_list_last(&wpa_s->mesh_external_pmksa_cache,
+ struct external_pmksa_cache,
+ list)) != NULL) {
+ dl_list_del(&entry->list);
+ os_free(entry->pmksa_cache);
+ os_free(entry);
+ }
+ }
+#endif /* CONFIG_MESH */
+#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
+
+ wpas_flush_fils_hlp_req(wpa_s);
+
+ wpabuf_free(wpa_s->ric_ies);
+ wpa_s->ric_ies = NULL;
+
+#ifdef CONFIG_DPP
+ wpas_dpp_deinit(wpa_s);
+ dpp_global_deinit(wpa_s->dpp);
+ wpa_s->dpp = NULL;
+#endif /* CONFIG_DPP */
}
@@ -755,6 +851,23 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
wpa_supplicant_state_txt(wpa_s->wpa_state),
wpa_supplicant_state_txt(state));
+ if (state == WPA_COMPLETED &&
+ os_reltime_initialized(&wpa_s->roam_start)) {
+ os_reltime_age(&wpa_s->roam_start, &wpa_s->roam_time);
+ wpa_s->roam_start.sec = 0;
+ wpa_s->roam_start.usec = 0;
+ wpas_notify_auth_changed(wpa_s);
+ wpas_notify_roam_time(wpa_s);
+ wpas_notify_roam_complete(wpa_s);
+ } else if (state == WPA_DISCONNECTED &&
+ os_reltime_initialized(&wpa_s->roam_start)) {
+ wpa_s->roam_start.sec = 0;
+ wpa_s->roam_start.usec = 0;
+ wpa_s->roam_time.sec = 0;
+ wpa_s->roam_time.usec = 0;
+ wpas_notify_roam_complete(wpa_s);
+ }
+
if (state == WPA_INTERFACE_DISABLED) {
/* Assure normal scan when interface is restored */
wpa_s->normal_scans = 0;
@@ -795,12 +908,24 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
if (state == WPA_COMPLETED && wpa_s->new_connection) {
struct wpa_ssid *ssid = wpa_s->current_ssid;
+ int fils_hlp_sent = 0;
+
+#ifdef CONFIG_SME
+ if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
+ wpa_auth_alg_fils(wpa_s->sme.auth_alg))
+ fils_hlp_sent = 1;
+#endif /* CONFIG_SME */
+ if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
+ wpa_auth_alg_fils(wpa_s->auth_alg))
+ fils_hlp_sent = 1;
+
#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
- MACSTR " completed [id=%d id_str=%s]",
+ MACSTR " completed [id=%d id_str=%s%s]",
MAC2STR(wpa_s->bssid),
ssid ? ssid->id : -1,
- ssid && ssid->id_str ? ssid->id_str : "");
+ ssid && ssid->id_str ? ssid->id_str : "",
+ fils_hlp_sent ? " FILS_HLP_SENT" : "");
#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
wpas_clear_temp_disabled(wpa_s, ssid, 1);
wpa_blacklist_clear(wpa_s);
@@ -815,6 +940,11 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
wpas_p2p_completed(wpa_s);
sme_sched_obss_scan(wpa_s, 1);
+
+#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
+ if (!fils_hlp_sent && ssid && ssid->eap.erp)
+ wpas_update_fils_connect_params(wpa_s);
+#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
} else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
state == WPA_ASSOCIATED) {
wpa_s->new_connection = 1;
@@ -833,7 +963,7 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
wpa_supplicant_stop_bgscan(wpa_s);
#endif /* CONFIG_BGSCAN */
- if (state == WPA_AUTHENTICATING)
+ if (state > WPA_SCANNING)
wpa_supplicant_stop_autoscan(wpa_s);
if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
@@ -929,7 +1059,13 @@ int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
"file '%s' - exiting", wpa_s->confname);
return -1;
}
- wpa_config_read(wpa_s->confanother, conf);
+ if (wpa_s->confanother &&
+ !wpa_config_read(wpa_s->confanother, conf)) {
+ wpa_msg(wpa_s, MSG_ERROR,
+ "Failed to parse the configuration file '%s' - exiting",
+ wpa_s->confanother);
+ return -1;
+ }
conf->changed_parameters = (unsigned int) -1;
@@ -955,7 +1091,9 @@ int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
* TODO: should notify EAPOL SM about changes in opensc_engine_path,
* pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
*/
- if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
+ if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
+ wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
+ wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
/*
* Clear forced success to clear EAP state for next
* authentication.
@@ -1056,6 +1194,18 @@ static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
}
+static int matching_ciphers(struct wpa_ssid *ssid, struct wpa_ie_data *ie,
+ int freq)
+{
+ if (!ie->has_group)
+ ie->group_cipher = wpa_default_rsn_cipher(freq);
+ if (!ie->has_pairwise)
+ ie->pairwise_cipher = wpa_default_rsn_cipher(freq);
+ return (ie->group_cipher & ssid->group_cipher) &&
+ (ie->pairwise_cipher & ssid->pairwise_cipher);
+}
+
+
/**
* wpa_supplicant_set_suites - Set authentication and encryption parameters
* @wpa_s: Pointer to wpa_supplicant data
@@ -1087,8 +1237,7 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
- (ie.group_cipher & ssid->group_cipher) &&
- (ie.pairwise_cipher & ssid->pairwise_cipher) &&
+ matching_ciphers(ssid, &ie, bss->freq) &&
(ie.key_mgmt & ssid->key_mgmt)) {
wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
proto = WPA_PROTO_RSN;
@@ -1100,14 +1249,20 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
proto = WPA_PROTO_WPA;
#ifdef CONFIG_HS20
- } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN)) {
+ } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN) &&
+ wpa_parse_wpa_ie(bss_osen, 2 + bss_osen[1], &ie) == 0 &&
+ (ie.group_cipher & ssid->group_cipher) &&
+ (ie.pairwise_cipher & ssid->pairwise_cipher) &&
+ (ie.key_mgmt & ssid->key_mgmt)) {
wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
- /* TODO: parse OSEN element */
- os_memset(&ie, 0, sizeof(ie));
- ie.group_cipher = WPA_CIPHER_CCMP;
- ie.pairwise_cipher = WPA_CIPHER_CCMP;
- ie.key_mgmt = WPA_KEY_MGMT_OSEN;
proto = WPA_PROTO_OSEN;
+ } else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) &&
+ wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
+ (ie.group_cipher & ssid->group_cipher) &&
+ (ie.pairwise_cipher & ssid->pairwise_cipher) &&
+ (ie.key_mgmt & ssid->key_mgmt)) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using OSEN (within RSN)");
+ proto = WPA_PROTO_RSN;
#endif /* CONFIG_HS20 */
} else if (bss) {
wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
@@ -1159,10 +1314,35 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
ie.pairwise_cipher = ssid->pairwise_cipher;
ie.key_mgmt = ssid->key_mgmt;
#ifdef CONFIG_IEEE80211W
- ie.mgmt_group_cipher =
- ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
- WPA_CIPHER_AES_128_CMAC : 0;
+ ie.mgmt_group_cipher = 0;
+ if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
+ if (ssid->group_mgmt_cipher &
+ WPA_CIPHER_BIP_GMAC_256)
+ ie.mgmt_group_cipher =
+ WPA_CIPHER_BIP_GMAC_256;
+ else if (ssid->group_mgmt_cipher &
+ WPA_CIPHER_BIP_CMAC_256)
+ ie.mgmt_group_cipher =
+ WPA_CIPHER_BIP_CMAC_256;
+ else if (ssid->group_mgmt_cipher &
+ WPA_CIPHER_BIP_GMAC_128)
+ ie.mgmt_group_cipher =
+ WPA_CIPHER_BIP_GMAC_128;
+ else
+ ie.mgmt_group_cipher =
+ WPA_CIPHER_AES_128_CMAC;
+ }
#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_OWE
+ if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
+ !ssid->owe_only &&
+ !bss_wpa && !bss_rsn && !bss_osen) {
+ wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
+ wpa_s->wpa_proto = 0;
+ *wpa_ie_len = 0;
+ return 0;
+ }
+#endif /* CONFIG_OWE */
wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
"based on configuration");
} else
@@ -1197,6 +1377,9 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
#else /* CONFIG_NO_WPA */
sel = ie.group_cipher & ssid->group_cipher;
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "WPA: AP group 0x%x network profile group 0x%x; available group 0x%x",
+ ie.group_cipher, ssid->group_cipher, sel);
wpa_s->group_cipher = wpa_pick_group_cipher(sel);
if (wpa_s->group_cipher < 0) {
wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
@@ -1207,6 +1390,9 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
wpa_cipher_txt(wpa_s->group_cipher));
sel = ie.pairwise_cipher & ssid->pairwise_cipher;
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "WPA: AP pairwise 0x%x network profile pairwise 0x%x; available pairwise 0x%x",
+ ie.pairwise_cipher, ssid->pairwise_cipher, sel);
wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
if (wpa_s->pairwise_cipher < 0) {
wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
@@ -1218,11 +1404,29 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_NO_WPA */
sel = ie.key_mgmt & ssid->key_mgmt;
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x",
+ ie.key_mgmt, ssid->key_mgmt, sel);
#ifdef CONFIG_SAE
if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
#endif /* CONFIG_SAE */
if (0) {
+#ifdef CONFIG_IEEE80211R
+#ifdef CONFIG_SHA384
+ } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) {
+ wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "WPA: using KEY_MGMT FT/802.1X-SHA384");
+ if (pmksa_cache_get_current(wpa_s->wpa)) {
+ /* PMKSA caching with FT is not fully functional, so
+ * disable the case for now. */
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "WPA: Disable PMKSA caching for FT/802.1X connection");
+ pmksa_cache_clear_current(wpa_s->wpa);
+ }
+#endif /* CONFIG_SHA384 */
+#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_SUITEB192
} else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
@@ -1235,22 +1439,52 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
wpa_dbg(wpa_s, MSG_DEBUG,
"WPA: using KEY_MGMT 802.1X with Suite B");
#endif /* CONFIG_SUITEB */
+#ifdef CONFIG_FILS
+#ifdef CONFIG_IEEE80211R
+ } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
+ wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
+ } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
+ wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
+#endif /* CONFIG_IEEE80211R */
+ } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
+ wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
+ } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
+ wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
+#endif /* CONFIG_FILS */
#ifdef CONFIG_IEEE80211R
} else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
- } else if (sel & WPA_KEY_MGMT_FT_PSK) {
- wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
- wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
+ if (pmksa_cache_get_current(wpa_s->wpa)) {
+ /* PMKSA caching with FT is not fully functional, so
+ * disable the case for now. */
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "WPA: Disable PMKSA caching for FT/802.1X connection");
+ pmksa_cache_clear_current(wpa_s->wpa);
+ }
#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_DPP
+ } else if (sel & WPA_KEY_MGMT_DPP) {
+ wpa_s->key_mgmt = WPA_KEY_MGMT_DPP;
+ wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP");
+#endif /* CONFIG_DPP */
#ifdef CONFIG_SAE
- } else if (sel & WPA_KEY_MGMT_SAE) {
- wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
- wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
} else if (sel & WPA_KEY_MGMT_FT_SAE) {
wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
+ } else if (sel & WPA_KEY_MGMT_SAE) {
+ wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
+ wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
#endif /* CONFIG_SAE */
+#ifdef CONFIG_IEEE80211R
+ } else if (sel & WPA_KEY_MGMT_FT_PSK) {
+ wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
+#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_IEEE80211W
} else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
@@ -1275,6 +1509,11 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
#endif /* CONFIG_HS20 */
+#ifdef CONFIG_OWE
+ } else if (sel & WPA_KEY_MGMT_OWE) {
+ wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
+ wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
+#endif /* CONFIG_OWE */
} else {
wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
"authenticated key management type");
@@ -1288,9 +1527,14 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
#ifdef CONFIG_IEEE80211W
sel = ie.mgmt_group_cipher;
+ if (ssid->group_mgmt_cipher)
+ sel &= ssid->group_mgmt_cipher;
if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
!(ie.capabilities & WPA_CAPABILITY_MFPC))
sel = 0;
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
+ ie.mgmt_group_cipher, ssid->group_mgmt_cipher, sel);
if (sel & WPA_CIPHER_AES_128_CMAC) {
wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
@@ -1316,23 +1560,44 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
wpas_get_ssid_pmf(wpa_s, ssid));
#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_OCV
+ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
+#endif /* CONFIG_OCV */
if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
return -1;
}
- if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
+ if (0) {
+#ifdef CONFIG_DPP
+ } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
+ /* Use PMK from DPP network introduction (PMKSA entry) */
+ wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
+#endif /* CONFIG_DPP */
+ } else if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
int psk_set = 0;
+ int sae_only;
+
+ sae_only = (ssid->key_mgmt & (WPA_KEY_MGMT_PSK |
+ WPA_KEY_MGMT_FT_PSK |
+ WPA_KEY_MGMT_PSK_SHA256)) == 0;
- if (ssid->psk_set) {
+ if (ssid->psk_set && !sae_only) {
+ wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)",
+ ssid->psk, PMK_LEN);
wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
NULL);
psk_set = 1;
}
+
+ if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
+ (ssid->sae_password || ssid->passphrase))
+ psk_set = 1;
+
#ifndef CONFIG_NO_PBKDF2
if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
- ssid->passphrase) {
+ ssid->passphrase && !sae_only) {
u8 psk[PMK_LEN];
pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
4096, psk, PMK_LEN);
@@ -1344,7 +1609,7 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
}
#endif /* CONFIG_NO_PBKDF2 */
#ifdef CONFIG_EXT_PASSWORD
- if (ssid->ext_psk) {
+ if (ssid->ext_psk && !sae_only) {
struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
ssid->ext_psk);
char pw_str[64 + 1];
@@ -1390,6 +1655,9 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
ext_password_free(pw);
return -1;
}
+ wpa_hexdump_key(MSG_MSGDUMP,
+ "PSK (from external PSK)",
+ psk, PMK_LEN);
wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
NULL);
psk_set = 1;
@@ -1410,8 +1678,15 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
if (!psk_set) {
wpa_msg(wpa_s, MSG_INFO,
"No PSK available for association");
+ wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE");
return -1;
}
+#ifdef CONFIG_OWE
+ } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
+ /* OWE Diffie-Hellman exchange in (Re)Association
+ * Request/Response frames set the PMK, so do not override it
+ * here. */
+#endif /* CONFIG_OWE */
} else
wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
@@ -1427,6 +1702,10 @@ static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
case 0: /* Bits 0-7 */
break;
case 1: /* Bits 8-15 */
+ if (wpa_s->conf->coloc_intf_reporting) {
+ /* Bit 13 - Collocated Interference Reporting */
+ *pos |= 0x20;
+ }
break;
case 2: /* Bits 16-23 */
#ifdef CONFIG_WNM
@@ -1445,7 +1724,7 @@ static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
break;
case 4: /* Bits 32-39 */
#ifdef CONFIG_INTERWORKING
- if (wpa_s->drv_flags / WPA_DRIVER_FLAGS_QOS_MAPPING)
+ if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
*pos |= 0x01; /* Bit 32 - QoS Map */
#endif /* CONFIG_INTERWORKING */
break;
@@ -1468,6 +1747,12 @@ static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
if (wpa_s->conf->ftm_initiator)
*pos |= 0x80; /* Bit 71 - FTM initiator */
break;
+ case 9: /* Bits 72-79 */
+#ifdef CONFIG_FILS
+ if (!wpa_s->disable_fils)
+ *pos |= 0x01;
+#endif /* CONFIG_FILS */
+ break;
}
}
@@ -1475,11 +1760,8 @@ static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
{
u8 *pos = buf;
- u8 len = 6, i;
+ u8 len = 10, i;
- if (len < 9 &&
- (wpa_s->conf->ftm_initiator || wpa_s->conf->ftm_responder))
- len = 9;
if (len < wpa_s->extended_capa_len)
len = wpa_s->extended_capa_len;
if (buflen < (size_t) len + 2) {
@@ -1667,6 +1949,9 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
wmm_ac_clear_saved_tspecs(wpa_s);
wpa_s->reassoc_same_bss = 0;
wpa_s->reassoc_same_ess = 0;
+#ifdef CONFIG_TESTING_OPTIONS
+ wpa_s->testing_resend_assoc = 0;
+#endif /* CONFIG_TESTING_OPTIONS */
if (wpa_s->last_ssid == ssid) {
wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
@@ -1674,12 +1959,16 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
if (wpa_s->current_bss && wpa_s->current_bss == bss) {
wmm_ac_save_tspecs(wpa_s);
wpa_s->reassoc_same_bss = 1;
+ } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
+ os_get_reltime(&wpa_s->roam_start);
}
- } else if (rand_style > 0) {
+ }
+
+ if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
if (wpas_update_random_addr(wpa_s, rand_style) < 0)
return;
wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
- } else if (wpa_s->mac_addr_changed) {
+ } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
wpa_msg(wpa_s, MSG_INFO,
"Could not restore permanent MAC address");
@@ -1698,6 +1987,13 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
#ifdef CONFIG_IBSS_RSN
ibss_rsn_deinit(wpa_s->ibss_rsn);
wpa_s->ibss_rsn = NULL;
+#else /* CONFIG_IBSS_RSN */
+ if (ssid->mode == WPAS_MODE_IBSS &&
+ !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "IBSS RSN not supported in the build");
+ return;
+ }
#endif /* CONFIG_IBSS_RSN */
if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
@@ -1739,6 +2035,7 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
ssid->id);
+ wpas_notify_mesh_group_started(wpa_s, ssid);
#else /* CONFIG_MESH */
wpa_msg(wpa_s, MSG_ERROR,
"mesh mode support not included in the build");
@@ -1746,6 +2043,20 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
return;
}
+ /*
+ * Set WPA state machine configuration to match the selected network now
+ * so that the information is available before wpas_start_assoc_cb()
+ * gets called. This is needed at least for RSN pre-authentication where
+ * candidate APs are added to a list based on scan result processing
+ * before completion of the first association.
+ */
+ wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
+
+#ifdef CONFIG_DPP
+ if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
+ return;
+#endif /* CONFIG_DPP */
+
#ifdef CONFIG_TDLS
if (bss)
wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
@@ -1768,6 +2079,13 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
return;
}
+#ifdef CONFIG_SME
+ if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
+ /* Clear possibly set auth_alg, if any, from last attempt. */
+ wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
+ }
+#endif /* CONFIG_SME */
+
wpas_abort_ongoing_scan(wpa_s);
cwork = os_zalloc(sizeof(*cwork));
@@ -1799,11 +2117,6 @@ static int drv_supports_vht(struct wpa_supplicant *wpa_s,
u8 channel;
int i;
-#ifdef CONFIG_HT_OVERRIDES
- if (ssid->disable_ht)
- return 0;
-#endif /* CONFIG_HT_OVERRIDES */
-
hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
if (hw_mode == NUM_HOSTAPD_MODES)
return 0;
@@ -1916,9 +2229,14 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
return;
+ freq->channel = pri_chan->chan;
+
#ifdef CONFIG_HT_OVERRIDES
- if (ssid->disable_ht40)
- return;
+ if (ssid->disable_ht40) {
+ if (ssid->disable_vht)
+ return;
+ goto skip_ht40;
+ }
#endif /* CONFIG_HT_OVERRIDES */
/* Check/setup HT40+/HT40- */
@@ -1943,8 +2261,6 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
return;
- freq->channel = pri_chan->chan;
-
if (ht40 == -1) {
if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
return;
@@ -1988,6 +2304,9 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
wpa_scan_results_free(scan_res);
}
+#ifdef CONFIG_HT_OVERRIDES
+skip_ht40:
+#endif /* CONFIG_HT_OVERRIDES */
wpa_printf(MSG_DEBUG,
"IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
freq->channel, freq->sec_channel_offset);
@@ -2002,6 +2321,13 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
vht_freq = *freq;
+#ifdef CONFIG_VHT_OVERRIDES
+ if (ssid->disable_vht) {
+ freq->vht_enabled = 0;
+ return;
+ }
+#endif /* CONFIG_VHT_OVERRIDES */
+
vht_freq.vht_enabled = vht_supported(mode);
if (!vht_freq.vht_enabled)
return;
@@ -2070,6 +2396,13 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
seg0 = 114;
}
+ } else if (ssid->max_oper_chwidth == VHT_CHANWIDTH_USE_HT) {
+ chwidth = VHT_CHANWIDTH_USE_HT;
+ seg0 = vht80[j] + 2;
+#ifdef CONFIG_HT_OVERRIDES
+ if (ssid->disable_ht40)
+ seg0 = 0;
+#endif /* CONFIG_HT_OVERRIDES */
}
if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
@@ -2086,147 +2419,177 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
}
-static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
+#ifdef CONFIG_FILS
+static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
+ size_t ie_buf_len)
{
- struct wpa_connect_work *cwork = work->ctx;
- struct wpa_bss *bss = cwork->bss;
- struct wpa_ssid *ssid = cwork->ssid;
- struct wpa_supplicant *wpa_s = work->wpa_s;
- u8 wpa_ie[200];
- size_t wpa_ie_len;
- int use_crypt, ret, i, bssid_changed;
- int algs = WPA_AUTH_ALG_OPEN;
- unsigned int cipher_pairwise, cipher_group;
- struct wpa_driver_associate_params params;
- int wep_keys_set = 0;
- int assoc_failed = 0;
- struct wpa_ssid *old_ssid;
- u8 prev_bssid[ETH_ALEN];
-#ifdef CONFIG_HT_OVERRIDES
- struct ieee80211_ht_capabilities htcaps;
- struct ieee80211_ht_capabilities htcaps_mask;
-#endif /* CONFIG_HT_OVERRIDES */
-#ifdef CONFIG_VHT_OVERRIDES
- struct ieee80211_vht_capabilities vhtcaps;
- struct ieee80211_vht_capabilities vhtcaps_mask;
-#endif /* CONFIG_VHT_OVERRIDES */
-#ifdef CONFIG_MBO
- const u8 *mbo = NULL;
-#endif /* CONFIG_MBO */
+ struct fils_hlp_req *req;
+ size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
+ const u8 *pos;
+ u8 *buf = ie_buf;
- if (deinit) {
- if (work->started) {
- wpa_s->connect_work = NULL;
+ dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
+ list) {
+ rem_len = ie_buf_len - ie_len;
+ pos = wpabuf_head(req->pkt);
+ hdr_len = 1 + 2 * ETH_ALEN + 6;
+ hlp_len = wpabuf_len(req->pkt);
- /* cancel possible auth. timeout */
- eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
- NULL);
+ if (rem_len < 2 + hdr_len + hlp_len) {
+ wpa_printf(MSG_ERROR,
+ "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
+ (unsigned long) rem_len,
+ (unsigned long) (2 + hdr_len + hlp_len));
+ break;
+ }
+
+ len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
+ /* Element ID */
+ *buf++ = WLAN_EID_EXTENSION;
+ /* Length */
+ *buf++ = len;
+ /* Element ID Extension */
+ *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
+ /* Destination MAC address */
+ os_memcpy(buf, req->dst, ETH_ALEN);
+ buf += ETH_ALEN;
+ /* Source MAC address */
+ os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
+ buf += ETH_ALEN;
+ /* LLC/SNAP Header */
+ os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
+ buf += 6;
+ /* HLP Packet */
+ os_memcpy(buf, pos, len - hdr_len);
+ buf += len - hdr_len;
+ pos += len - hdr_len;
+
+ hlp_len -= len - hdr_len;
+ ie_len += 2 + len;
+ rem_len -= 2 + len;
+
+ while (hlp_len) {
+ len = (hlp_len > 255) ? 255 : hlp_len;
+ if (rem_len < 2 + len)
+ break;
+ *buf++ = WLAN_EID_FRAGMENT;
+ *buf++ = len;
+ os_memcpy(buf, pos, len);
+ buf += len;
+ pos += len;
+
+ hlp_len -= len;
+ ie_len += 2 + len;
+ rem_len -= 2 + len;
}
- wpas_connect_work_free(cwork);
- return;
}
- wpa_s->connect_work = work;
+ return ie_len;
+}
- if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
- wpas_network_disabled(wpa_s, ssid)) {
- wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
- wpas_connect_work_done(wpa_s);
- return;
- }
- os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
- os_memset(&params, 0, sizeof(params));
- wpa_s->reassociate = 0;
- wpa_s->eap_expected_failure = 0;
- if (bss &&
- (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
-#ifdef CONFIG_IEEE80211R
- const u8 *ie, *md = NULL;
-#endif /* CONFIG_IEEE80211R */
- wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
- " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
- wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
- bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
- os_memset(wpa_s->bssid, 0, ETH_ALEN);
- os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
- if (bssid_changed)
- wpas_notify_bssid_changed(wpa_s);
-#ifdef CONFIG_IEEE80211R
- ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
- if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
- md = ie + 2;
- wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
- if (md) {
- /* Prepare for the next transition */
- wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
- }
-#endif /* CONFIG_IEEE80211R */
-#ifdef CONFIG_WPS
- } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
- wpa_s->conf->ap_scan == 2 &&
- (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
- /* Use ap_scan==1 style network selection to find the network
- */
- wpas_connect_work_done(wpa_s);
- wpa_s->scan_req = MANUAL_SCAN_REQ;
- wpa_s->reassociate = 1;
- wpa_supplicant_req_scan(wpa_s, 0, 0);
- return;
-#endif /* CONFIG_WPS */
- } else {
- wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
- wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
- if (bss)
- os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
- else
- os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
- }
- if (!wpa_s->pno)
- wpa_supplicant_cancel_sched_scan(wpa_s);
+int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
+{
+ return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
+ (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
+ (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
+ (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
+}
- wpa_supplicant_cancel_scan(wpa_s);
- /* Starting new association, so clear the possibly used WPA IE from the
- * previous association. */
- wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
+int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
+{
+#ifdef CONFIG_FILS_SK_PFS
+ return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
+ (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
+#else /* CONFIG_FILS_SK_PFS */
+ return 0;
+#endif /* CONFIG_FILS_SK_PFS */
+}
-#ifdef IEEE8021X_EAPOL
- if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
- if (ssid->leap) {
- if (ssid->non_leap == 0)
- algs = WPA_AUTH_ALG_LEAP;
- else
- algs |= WPA_AUTH_ALG_LEAP;
- }
+#endif /* CONFIG_FILS */
+
+
+static u8 * wpas_populate_assoc_ies(
+ struct wpa_supplicant *wpa_s,
+ struct wpa_bss *bss, struct wpa_ssid *ssid,
+ struct wpa_driver_associate_params *params,
+ enum wpa_drv_update_connect_params_mask *mask)
+{
+ u8 *wpa_ie;
+ size_t max_wpa_ie_len = 500;
+ size_t wpa_ie_len;
+ int algs = WPA_AUTH_ALG_OPEN;
+#ifdef CONFIG_MBO
+ const u8 *mbo_ie;
+#endif
+#ifdef CONFIG_SAE
+ int sae_pmksa_cached = 0;
+#endif /* CONFIG_SAE */
+#ifdef CONFIG_FILS
+ const u8 *realm, *username, *rrk;
+ size_t realm_len, username_len, rrk_len;
+ u16 next_seq_num;
+ struct fils_hlp_req *req;
+
+ dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
+ list) {
+ max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
+ 2 + 2 * wpabuf_len(req->pkt) / 255;
}
-#endif /* IEEE8021X_EAPOL */
- wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
- if (ssid->auth_alg) {
- algs = ssid->auth_alg;
- wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
- "0x%x", algs);
+#endif /* CONFIG_FILS */
+
+ wpa_ie = os_malloc(max_wpa_ie_len);
+ if (!wpa_ie) {
+ wpa_printf(MSG_ERROR,
+ "Failed to allocate connect IE buffer for %lu bytes",
+ (unsigned long) max_wpa_ie_len);
+ return NULL;
}
if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
wpa_key_mgmt_wpa(ssid->key_mgmt)) {
int try_opportunistic;
+ const u8 *cache_id = NULL;
+
try_opportunistic = (ssid->proactive_key_caching < 0 ?
wpa_s->conf->okc :
ssid->proactive_key_caching) &&
(ssid->proto & WPA_PROTO_RSN);
+#ifdef CONFIG_FILS
+ if (wpa_key_mgmt_fils(ssid->key_mgmt))
+ cache_id = wpa_bss_get_fils_cache_id(bss);
+#endif /* CONFIG_FILS */
if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
- ssid, try_opportunistic) == 0)
+ ssid, try_opportunistic,
+ cache_id, 0) == 0) {
eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
- wpa_ie_len = sizeof(wpa_ie);
+#ifdef CONFIG_SAE
+ sae_pmksa_cached = 1;
+#endif /* CONFIG_SAE */
+ }
+ wpa_ie_len = max_wpa_ie_len;
if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
wpa_ie, &wpa_ie_len)) {
wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
"key management and encryption suites");
- wpas_connect_work_done(wpa_s);
- return;
+ os_free(wpa_ie);
+ return NULL;
}
+#ifdef CONFIG_HS20
+ } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
+ (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
+ /* No PMKSA caching, but otherwise similar to RSN/WPA */
+ wpa_ie_len = max_wpa_ie_len;
+ if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
+ wpa_ie, &wpa_ie_len)) {
+ wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
+ "key management and encryption suites");
+ os_free(wpa_ie);
+ return NULL;
+ }
+#endif /* CONFIG_HS20 */
} else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
/*
@@ -2238,20 +2601,20 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
wpa_ie_len = 0;
wpa_s->wpa_proto = 0;
} else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
- wpa_ie_len = sizeof(wpa_ie);
+ wpa_ie_len = max_wpa_ie_len;
if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
wpa_ie, &wpa_ie_len)) {
wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
"key management and encryption suites (no "
"scan results)");
- wpas_connect_work_done(wpa_s);
- return;
+ os_free(wpa_ie);
+ return NULL;
}
#ifdef CONFIG_WPS
} else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
struct wpabuf *wps_ie;
wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
- if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
+ if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
wpa_ie_len = wpabuf_len(wps_ie);
os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
} else
@@ -2259,9 +2622,9 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
wpabuf_free(wps_ie);
wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
- params.wps = WPS_MODE_PRIVACY;
+ params->wps = WPS_MODE_PRIVACY;
else
- params.wps = WPS_MODE_OPEN;
+ params->wps = WPS_MODE_OPEN;
wpa_s->wpa_proto = 0;
#endif /* CONFIG_WPS */
} else {
@@ -2270,13 +2633,69 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
wpa_s->wpa_proto = 0;
}
+#ifdef IEEE8021X_EAPOL
+ if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
+ if (ssid->leap) {
+ if (ssid->non_leap == 0)
+ algs = WPA_AUTH_ALG_LEAP;
+ else
+ algs |= WPA_AUTH_ALG_LEAP;
+ }
+ }
+
+#ifdef CONFIG_FILS
+ /* Clear FILS association */
+ wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
+
+ if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
+ ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
+ eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
+ &username_len, &realm, &realm_len,
+ &next_seq_num, &rrk, &rrk_len) == 0 &&
+ (!wpa_s->last_con_fail_realm ||
+ wpa_s->last_con_fail_realm_len != realm_len ||
+ os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
+ algs = WPA_AUTH_ALG_FILS;
+ params->fils_erp_username = username;
+ params->fils_erp_username_len = username_len;
+ params->fils_erp_realm = realm;
+ params->fils_erp_realm_len = realm_len;
+ params->fils_erp_next_seq_num = next_seq_num;
+ params->fils_erp_rrk = rrk;
+ params->fils_erp_rrk_len = rrk_len;
+
+ if (mask)
+ *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
+ }
+#endif /* CONFIG_FILS */
+#endif /* IEEE8021X_EAPOL */
+#ifdef CONFIG_SAE
+ if (wpa_s->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE))
+ algs = WPA_AUTH_ALG_SAE;
+#endif /* CONFIG_SAE */
+
+ wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
+ if (ssid->auth_alg) {
+ algs = ssid->auth_alg;
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Overriding auth_alg selection: 0x%x", algs);
+ }
+
+#ifdef CONFIG_SAE
+ if (sae_pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
+ algs = WPA_AUTH_ALG_OPEN;
+ }
+#endif /* CONFIG_SAE */
+
#ifdef CONFIG_P2P
if (wpa_s->global->p2p) {
u8 *pos;
size_t len;
int res;
pos = wpa_ie + wpa_ie_len;
- len = sizeof(wpa_ie) - wpa_ie_len;
+ len = max_wpa_ie_len - wpa_ie_len;
res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
ssid->p2p_group);
if (res >= 0)
@@ -2301,21 +2720,12 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
#endif /* CONFIG_P2P */
-#ifdef CONFIG_MBO
if (bss) {
- mbo = wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE);
- if (mbo) {
- int len;
-
- len = wpas_mbo_supp_op_class_ie(wpa_s, bss->freq,
- wpa_ie + wpa_ie_len,
- sizeof(wpa_ie) -
- wpa_ie_len);
- if (len > 0)
- wpa_ie_len += len;
- }
+ wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss->freq,
+ wpa_ie + wpa_ie_len,
+ max_wpa_ie_len -
+ wpa_ie_len);
}
-#endif /* CONFIG_MBO */
/*
* Workaround: Add Extended Capabilities element only if the AP
@@ -2335,7 +2745,8 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
int ext_capab_len;
ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
sizeof(ext_capab));
- if (ext_capab_len > 0) {
+ if (ext_capab_len > 0 &&
+ wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
u8 *pos = wpa_ie;
if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
pos += 2 + pos[1];
@@ -2350,13 +2761,15 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
if (is_hs20_network(wpa_s, ssid, bss)) {
struct wpabuf *hs20;
- hs20 = wpabuf_alloc(20);
+ hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
if (hs20) {
int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
size_t len;
- wpas_hs20_add_indication(hs20, pps_mo_id);
- len = sizeof(wpa_ie) - wpa_ie_len;
+ wpas_hs20_add_indication(hs20, pps_mo_id,
+ get_hs20_version(bss));
+ wpas_hs20_add_roam_cons_sel(hs20, ssid);
+ len = max_wpa_ie_len - wpa_ie_len;
if (wpabuf_len(hs20) <= len) {
os_memcpy(wpa_ie + wpa_ie_len,
wpabuf_head(hs20), wpabuf_len(hs20));
@@ -2373,7 +2786,7 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
size_t len;
- len = sizeof(wpa_ie) - wpa_ie_len;
+ len = max_wpa_ie_len - wpa_ie_len;
if (wpabuf_len(buf) <= len) {
os_memcpy(wpa_ie + wpa_ie_len,
wpabuf_head(buf), wpabuf_len(buf));
@@ -2385,7 +2798,7 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
if (wpa_s->fst_ies) {
int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
- if (wpa_ie_len + fst_ies_len <= sizeof(wpa_ie)) {
+ if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
os_memcpy(wpa_ie + wpa_ie_len,
wpabuf_head(wpa_s->fst_ies), fst_ies_len);
wpa_ie_len += fst_ies_len;
@@ -2394,20 +2807,314 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
#endif /* CONFIG_FST */
#ifdef CONFIG_MBO
- if (mbo) {
+ mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
+ if (mbo_ie) {
int len;
len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
- sizeof(wpa_ie) - wpa_ie_len);
+ max_wpa_ie_len - wpa_ie_len,
+ !!mbo_attr_from_mbo_ie(mbo_ie,
+ OCE_ATTR_ID_CAPA_IND));
if (len >= 0)
wpa_ie_len += len;
}
#endif /* CONFIG_MBO */
+#ifdef CONFIG_FILS
+ if (algs == WPA_AUTH_ALG_FILS) {
+ size_t len;
+
+ len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
+ max_wpa_ie_len - wpa_ie_len);
+ wpa_ie_len += len;
+ }
+#endif /* CONFIG_FILS */
+
+#ifdef CONFIG_OWE
+#ifdef CONFIG_TESTING_OPTIONS
+ if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
+ wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
+ } else
+#endif /* CONFIG_TESTING_OPTIONS */
+ if (algs == WPA_AUTH_ALG_OPEN &&
+ ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
+ struct wpabuf *owe_ie;
+ u16 group;
+
+ if (ssid->owe_group) {
+ group = ssid->owe_group;
+ } else if (wpa_s->assoc_status_code ==
+ WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
+ if (wpa_s->last_owe_group == 19)
+ group = 20;
+ else if (wpa_s->last_owe_group == 20)
+ group = 21;
+ else
+ group = OWE_DH_GROUP;
+ } else {
+ group = OWE_DH_GROUP;
+ }
+
+ wpa_s->last_owe_group = group;
+ wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
+ owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
+ if (owe_ie &&
+ wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
+ os_memcpy(wpa_ie + wpa_ie_len,
+ wpabuf_head(owe_ie), wpabuf_len(owe_ie));
+ wpa_ie_len += wpabuf_len(owe_ie);
+ }
+ wpabuf_free(owe_ie);
+ }
+#endif /* CONFIG_OWE */
+
+#ifdef CONFIG_DPP2
+ if (wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
+ ssid->dpp_netaccesskey) {
+ dpp_pfs_free(wpa_s->dpp_pfs);
+ wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
+ ssid->dpp_netaccesskey_len);
+ if (!wpa_s->dpp_pfs) {
+ wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
+ /* Try to continue without PFS */
+ goto pfs_fail;
+ }
+ if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
+ max_wpa_ie_len - wpa_ie_len) {
+ os_memcpy(wpa_ie + wpa_ie_len,
+ wpabuf_head(wpa_s->dpp_pfs->ie),
+ wpabuf_len(wpa_s->dpp_pfs->ie));
+ wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
+ }
+ }
+pfs_fail:
+#endif /* CONFIG_DPP2 */
+
+#ifdef CONFIG_IEEE80211R
+ /*
+ * Add MDIE under these conditions: the network profile allows FT,
+ * the AP supports FT, and the mobility domain ID matches.
+ */
+ if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
+ const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
+
+ if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
+ size_t len = 0;
+ const u8 *md = mdie + 2;
+ const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
+
+ if (os_memcmp(md, wpa_md,
+ MOBILITY_DOMAIN_ID_LEN) == 0) {
+ /* Add mobility domain IE */
+ len = wpa_ft_add_mdie(
+ wpa_s->wpa, wpa_ie + wpa_ie_len,
+ max_wpa_ie_len - wpa_ie_len, mdie);
+ wpa_ie_len += len;
+ }
+#ifdef CONFIG_SME
+ if (len > 0 && wpa_s->sme.ft_used &&
+ wpa_sm_has_ptk(wpa_s->wpa)) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "SME: Trying to use FT over-the-air");
+ algs |= WPA_AUTH_ALG_FT;
+ }
+#endif /* CONFIG_SME */
+ }
+ }
+#endif /* CONFIG_IEEE80211R */
+
+ if (ssid->multi_ap_backhaul_sta) {
+ size_t multi_ap_ie_len;
+
+ multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
+ max_wpa_ie_len - wpa_ie_len,
+ MULTI_AP_BACKHAUL_STA);
+ if (multi_ap_ie_len == 0) {
+ wpa_printf(MSG_ERROR,
+ "Multi-AP: Failed to build Multi-AP IE");
+ os_free(wpa_ie);
+ return NULL;
+ }
+ wpa_ie_len += multi_ap_ie_len;
+ }
+
+ params->wpa_ie = wpa_ie;
+ params->wpa_ie_len = wpa_ie_len;
+ params->auth_alg = algs;
+ if (mask)
+ *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
+
+ return wpa_ie;
+}
+
+
+#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
+static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_driver_associate_params params;
+ enum wpa_drv_update_connect_params_mask mask = 0;
+ u8 *wpa_ie;
+
+ if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
+ return; /* nothing to do */
+
+ os_memset(&params, 0, sizeof(params));
+ wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
+ wpa_s->current_ssid, &params, &mask);
+ if (!wpa_ie)
+ return;
+
+ if (params.auth_alg != WPA_AUTH_ALG_FILS) {
+ os_free(wpa_ie);
+ return;
+ }
+
+ wpa_s->auth_alg = params.auth_alg;
+ wpa_drv_update_connect_params(wpa_s, &params, mask);
+ os_free(wpa_ie);
+}
+#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
+
+
+#ifdef CONFIG_MBO
+void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_driver_associate_params params;
+ u8 *wpa_ie;
+
+ /*
+ * Update MBO connect params only in case of change of MBO attributes
+ * when connected, if the AP support MBO.
+ */
+
+ if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
+ !wpa_s->current_bss ||
+ !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
+ return;
+
+ os_memset(&params, 0, sizeof(params));
+ wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
+ wpa_s->current_ssid, &params, NULL);
+ if (!wpa_ie)
+ return;
+
+ wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
+ os_free(wpa_ie);
+}
+#endif /* CONFIG_MBO */
+
+
+static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
+{
+ struct wpa_connect_work *cwork = work->ctx;
+ struct wpa_bss *bss = cwork->bss;
+ struct wpa_ssid *ssid = cwork->ssid;
+ struct wpa_supplicant *wpa_s = work->wpa_s;
+ u8 *wpa_ie;
+ int use_crypt, ret, i, bssid_changed;
+ unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
+ struct wpa_driver_associate_params params;
+ int wep_keys_set = 0;
+ int assoc_failed = 0;
+ struct wpa_ssid *old_ssid;
+ u8 prev_bssid[ETH_ALEN];
+#ifdef CONFIG_HT_OVERRIDES
+ struct ieee80211_ht_capabilities htcaps;
+ struct ieee80211_ht_capabilities htcaps_mask;
+#endif /* CONFIG_HT_OVERRIDES */
+#ifdef CONFIG_VHT_OVERRIDES
+ struct ieee80211_vht_capabilities vhtcaps;
+ struct ieee80211_vht_capabilities vhtcaps_mask;
+#endif /* CONFIG_VHT_OVERRIDES */
+
+ if (deinit) {
+ if (work->started) {
+ wpa_s->connect_work = NULL;
+
+ /* cancel possible auth. timeout */
+ eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
+ NULL);
+ }
+ wpas_connect_work_free(cwork);
+ return;
+ }
+
+ wpa_s->connect_work = work;
+
+ if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
+ wpas_network_disabled(wpa_s, ssid)) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
+ wpas_connect_work_done(wpa_s);
+ return;
+ }
+
+ os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
+ os_memset(&params, 0, sizeof(params));
+ wpa_s->reassociate = 0;
+ wpa_s->eap_expected_failure = 0;
+ if (bss &&
+ (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
+#ifdef CONFIG_IEEE80211R
+ const u8 *ie, *md = NULL;
+#endif /* CONFIG_IEEE80211R */
+ wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
+ " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
+ wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
+ bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
+ os_memset(wpa_s->bssid, 0, ETH_ALEN);
+ os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
+ if (bssid_changed)
+ wpas_notify_bssid_changed(wpa_s);
+#ifdef CONFIG_IEEE80211R
+ ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
+ if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
+ md = ie + 2;
+ wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
+ if (md) {
+ /* Prepare for the next transition */
+ wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
+ }
+#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_WPS
+ } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
+ wpa_s->conf->ap_scan == 2 &&
+ (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
+ /* Use ap_scan==1 style network selection to find the network
+ */
+ wpas_connect_work_done(wpa_s);
+ wpa_s->scan_req = MANUAL_SCAN_REQ;
+ wpa_s->reassociate = 1;
+ wpa_supplicant_req_scan(wpa_s, 0, 0);
+ return;
+#endif /* CONFIG_WPS */
+ } else {
+ wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
+ wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
+ if (bss)
+ os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
+ else
+ os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
+ }
+ if (!wpa_s->pno)
+ wpa_supplicant_cancel_sched_scan(wpa_s);
+
+ wpa_supplicant_cancel_scan(wpa_s);
+
+ /* Starting new association, so clear the possibly used WPA IE from the
+ * previous association. */
+ wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
+
+ wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
+ if (!wpa_ie) {
+ wpas_connect_work_done(wpa_s);
+ return;
+ }
+
wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
use_crypt = 1;
cipher_pairwise = wpa_s->pairwise_cipher;
cipher_group = wpa_s->group_cipher;
+ cipher_group_mgmt = wpa_s->mgmt_group_cipher;
if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
@@ -2445,12 +3152,14 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
if (bss) {
params.ssid = bss->ssid;
params.ssid_len = bss->ssid_len;
- if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
+ if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
+ wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
MACSTR " freq=%u MHz based on scan results "
- "(bssid_set=%d)",
+ "(bssid_set=%d wps=%d)",
MAC2STR(bss->bssid), bss->freq,
- ssid->bssid_set);
+ ssid->bssid_set,
+ wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
params.bssid = bss->bssid;
params.freq.freq = bss->freq;
}
@@ -2458,6 +3167,9 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
params.freq_hint = bss->freq;
params.pbss = bss_is_pbss(bss);
} else {
+ if (ssid->bssid_hint_set)
+ params.bssid_hint = ssid->bssid_hint;
+
params.ssid = ssid->ssid;
params.ssid_len = ssid->ssid_len;
params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
@@ -2482,13 +3194,12 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
params.beacon_int = wpa_s->conf->beacon_int;
}
- params.wpa_ie = wpa_ie;
- params.wpa_ie_len = wpa_ie_len;
params.pairwise_suite = cipher_pairwise;
params.group_suite = cipher_group;
+ params.mgmt_group_suite = cipher_group_mgmt;
params.key_mgmt_suite = wpa_s->key_mgmt;
params.wpa_proto = wpa_s->wpa_proto;
- params.auth_alg = algs;
+ wpa_s->auth_alg = params.auth_alg;
params.mode = ssid->mode;
params.bg_scan_period = ssid->bg_scan_period;
for (i = 0; i < NUM_WEP_KEYS; i++) {
@@ -2498,7 +3209,7 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
}
params.wep_tx_keyidx = ssid->wep_tx_keyidx;
- if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
+ if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
(params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
params.passphrase = ssid->passphrase;
@@ -2506,6 +3217,13 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
params.psk = ssid->psk;
}
+ if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
+ (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
+ params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
+ params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
+ params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192))
+ params.req_key_mgmt_offload = 1;
+
if (wpa_s->conf->key_mgmt_offload) {
if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
@@ -2538,6 +3256,11 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
"MFP: require MFP");
params.mgmt_frame_protection =
MGMT_FRAME_PROTECTION_REQUIRED;
+#ifdef CONFIG_OWE
+ } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
+ !ssid->owe_only) {
+ params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
+#endif /* CONFIG_OWE */
}
}
#endif /* CONFIG_IEEE80211W */
@@ -2580,6 +3303,7 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
if (wpas_p2p_handle_frequency_conflicts(
wpa_s, params.freq.freq, ssid) < 0) {
wpas_connect_work_done(wpa_s);
+ os_free(wpa_ie);
return;
}
}
@@ -2591,6 +3315,7 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
params.prev_bssid = prev_bssid;
ret = wpa_drv_associate(wpa_s, &params);
+ os_free(wpa_ie);
if (ret < 0) {
wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
"failed");
@@ -2726,14 +3451,22 @@ void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
zero_addr = 1;
}
+ if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
+ wpa_s->enabled_4addr_mode = 0;
+
#ifdef CONFIG_TDLS
wpa_tdls_teardown_peers(wpa_s->wpa);
#endif /* CONFIG_TDLS */
#ifdef CONFIG_MESH
if (wpa_s->ifmsh) {
+ struct mesh_conf *mconf;
+
+ mconf = wpa_s->ifmsh->mconf;
wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
wpa_s->ifname);
+ wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
+ mconf->meshid_len, reason_code);
wpa_supplicant_leave_mesh(wpa_s);
}
#endif /* CONFIG_MESH */
@@ -2758,6 +3491,7 @@ static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
return;
ssid->disabled = 0;
+ ssid->owe_transition_bss_select_count = 0;
wpas_clear_temp_disabled(wpa_s, ssid, 1);
wpas_notify_network_enabled_changed(wpa_s, ssid);
@@ -2923,13 +3657,19 @@ void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
wpas_notify_network_enabled_changed(
wpa_s, other_ssid);
}
- if (wpa_s->current_ssid)
+ if (wpa_s->current_ssid) {
+ if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
+ wpa_s->own_disconnect_req = 1;
wpa_supplicant_deauthenticate(
wpa_s, WLAN_REASON_DEAUTH_LEAVING);
+ }
} else if (ssid->disabled != 2) {
- if (ssid == wpa_s->current_ssid)
+ if (ssid == wpa_s->current_ssid) {
+ if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
+ wpa_s->own_disconnect_req = 1;
wpa_supplicant_deauthenticate(
wpa_s, WLAN_REASON_DEAUTH_LEAVING);
+ }
was_disabled = ssid->disabled;
@@ -3015,6 +3755,9 @@ void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
wpa_s->disconnected = 0;
wpa_s->reassociate = 1;
+ wpa_s->last_owe_group = 0;
+ if (ssid)
+ ssid->owe_transition_bss_select_count = 0;
if (wpa_s->connect_without_scan ||
wpa_supplicant_fast_associate(wpa_s) != 1) {
@@ -3232,6 +3975,41 @@ int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
}
+#ifdef CONFIG_OWE
+static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
+ const u8 *entry_ssid, size_t entry_ssid_len)
+{
+ const u8 *owe, *pos, *end;
+ u8 ssid_len;
+ struct wpa_bss *bss;
+
+ /* Check network profile SSID aganst the SSID in the
+ * OWE Transition Mode element. */
+
+ bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
+ if (!bss)
+ return 0;
+
+ owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
+ if (!owe)
+ return 0;
+
+ pos = owe + 6;
+ end = owe + 2 + owe[1];
+
+ if (end - pos < ETH_ALEN + 1)
+ return 0;
+ pos += ETH_ALEN;
+ ssid_len = *pos++;
+ if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
+ return 0;
+
+ return entry_ssid_len == ssid_len &&
+ os_memcmp(pos, entry_ssid, ssid_len) == 0;
+}
+#endif /* CONFIG_OWE */
+
+
/**
* wpa_supplicant_get_ssid - Get a pointer to the current network structure
* @wpa_s: Pointer to wpa_supplicant data
@@ -3267,7 +4045,9 @@ struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
while (entry) {
if (!wpas_network_disabled(wpa_s, entry) &&
((ssid_len == entry->ssid_len &&
- os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
+ (!entry->ssid ||
+ os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
+ wired) &&
(!entry->bssid_set ||
os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
return entry;
@@ -3280,6 +4060,15 @@ struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
return entry;
#endif /* CONFIG_WPS */
+#ifdef CONFIG_OWE
+ if (!wpas_network_disabled(wpa_s, entry) &&
+ owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
+ entry->ssid_len) &&
+ (!entry->bssid_set ||
+ os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
+ return entry;
+#endif /* CONFIG_OWE */
+
if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
entry->ssid_len == 0 &&
os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
@@ -3387,16 +4176,6 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
}
#endif /* CONFIG_TESTING_OPTIONS */
-#ifdef CONFIG_PEERKEY
- if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
- wpa_s->current_ssid->peerkey &&
- !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
- wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
- wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
- return;
- }
-#endif /* CONFIG_PEERKEY */
-
if (wpa_s->wpa_state < WPA_ASSOCIATED ||
(wpa_s->last_eapol_matches_bssid &&
#ifdef CONFIG_AP
@@ -3446,7 +4225,7 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
}
if (wpa_s->eapol_received == 0 &&
- (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
+ (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
wpa_s->wpa_state != WPA_COMPLETED) &&
(wpa_s->current_ssid == NULL ||
@@ -3507,10 +4286,12 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
+ wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
+ wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
return;
wpa_drv_poll(wpa_s);
- if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
+ if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
/*
@@ -3536,6 +4317,11 @@ int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
wpa_supplicant_rx_eapol, wpa_s, 0);
if (wpa_s->l2 == NULL)
return -1;
+
+ if (l2_packet_set_packet_filter(wpa_s->l2,
+ L2_PACKET_FILTER_PKTTYPE))
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Failed to attach pkt_type filter");
} else {
const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
if (addr)
@@ -3675,6 +4461,7 @@ wpa_supplicant_alloc(struct wpa_supplicant *parent)
wpa_s->sched_scanning = 0;
dl_list_init(&wpa_s->bss_tmp_disallowed);
+ dl_list_init(&wpa_s->fils_hlp_req);
return wpa_s;
}
@@ -3702,8 +4489,11 @@ static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
+ long v;
+
errno = 0;
- long v = strtol(tmp, &end, 16);
+ v = strtol(tmp, &end, 16);
+
if (errno == 0) {
wpa_msg(wpa_s, MSG_DEBUG,
"htcap value[%i]: %ld end: %p tmp: %p",
@@ -3743,11 +4533,11 @@ static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
{
le16 msk;
- wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
-
if (disabled == -1)
return 0;
+ wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
+
msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
htcaps_mask->ht_capabilities_info |= msk;
if (disabled)
@@ -3764,11 +4554,11 @@ static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
struct ieee80211_ht_capabilities *htcaps_mask,
int factor)
{
- wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
-
if (factor == -1)
return 0;
+ wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
+
if (factor < 0 || factor > 3) {
wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
"Must be 0-3 or -1", factor);
@@ -3788,11 +4578,11 @@ static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
struct ieee80211_ht_capabilities *htcaps_mask,
int density)
{
- wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
-
if (density == -1)
return 0;
+ wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
+
if (density < 0 || density > 7) {
wpa_msg(wpa_s, MSG_ERROR,
"ampdu_density: %d out of range. Must be 0-7 or -1.",
@@ -3813,18 +4603,11 @@ static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
struct ieee80211_ht_capabilities *htcaps_mask,
int disabled)
{
- /* Masking these out disables HT40 */
- le16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
- HT_CAP_INFO_SHORT_GI40MHZ);
-
- wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
-
if (disabled)
- htcaps->ht_capabilities_info &= ~msk;
- else
- htcaps->ht_capabilities_info |= msk;
+ wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
- htcaps_mask->ht_capabilities_info |= msk;
+ set_disable_ht40(htcaps, disabled);
+ set_disable_ht40(htcaps_mask, 0);
return 0;
}
@@ -3839,7 +4622,8 @@ static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
HT_CAP_INFO_SHORT_GI40MHZ);
- wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
+ if (disabled)
+ wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
if (disabled)
htcaps->ht_capabilities_info &= ~msk;
@@ -3860,7 +4644,8 @@ static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
/* Masking these out disables LDPC */
le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
- wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
+ if (disabled)
+ wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
if (disabled)
htcaps->ht_capabilities_info &= ~msk;
@@ -3873,6 +4658,58 @@ static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
}
+static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
+ struct ieee80211_ht_capabilities *htcaps,
+ struct ieee80211_ht_capabilities *htcaps_mask,
+ int tx_stbc)
+{
+ le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
+
+ if (tx_stbc == -1)
+ return 0;
+
+ wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
+
+ if (tx_stbc < 0 || tx_stbc > 1) {
+ wpa_msg(wpa_s, MSG_ERROR,
+ "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
+ return -EINVAL;
+ }
+
+ htcaps_mask->ht_capabilities_info |= msk;
+ htcaps->ht_capabilities_info &= ~msk;
+ htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
+
+ return 0;
+}
+
+
+static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
+ struct ieee80211_ht_capabilities *htcaps,
+ struct ieee80211_ht_capabilities *htcaps_mask,
+ int rx_stbc)
+{
+ le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
+
+ if (rx_stbc == -1)
+ return 0;
+
+ wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
+
+ if (rx_stbc < 0 || rx_stbc > 3) {
+ wpa_msg(wpa_s, MSG_ERROR,
+ "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
+ return -EINVAL;
+ }
+
+ htcaps_mask->ht_capabilities_info |= msk;
+ htcaps->ht_capabilities_info &= ~msk;
+ htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
+
+ return 0;
+}
+
+
void wpa_supplicant_apply_ht_overrides(
struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
struct wpa_driver_associate_params *params)
@@ -3897,6 +4734,8 @@ void wpa_supplicant_apply_ht_overrides(
wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
+ wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
+ wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
if (ssid->ht40_intolerant) {
le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
@@ -3931,6 +4770,16 @@ void wpa_supplicant_apply_vht_overrides(
vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
#ifdef CONFIG_HT_OVERRIDES
+ if (ssid->disable_sgi) {
+ vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
+ VHT_CAP_SHORT_GI_160);
+ vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
+ VHT_CAP_SHORT_GI_160);
+ wpa_msg(wpa_s, MSG_DEBUG,
+ "disable-sgi override specified, vht-caps: 0x%x",
+ vhtcaps->vht_capabilities_info);
+ }
+
/* if max ampdu is <= 3, we have to make the HT cap the same */
if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
int max_ampdu;
@@ -4100,10 +4949,14 @@ static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
{
struct wpa_supplicant *wpa_s = ctx;
- WPA_ASSERT(os_memcmp(wpa_s->bssid, da, ETH_ALEN) == 0);
+ if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
+ wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
+ __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
+ return -1;
+ }
return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
- wpa_s->own_addr, wpa_s->bssid,
- wpabuf_head(data), wpabuf_len(data),
+ wpa_s->own_addr, wpa_s->bssid,
+ wpabuf_head(data), wpabuf_len(data),
0);
}
@@ -4291,7 +5144,7 @@ static void radio_work_free(struct wpa_radio_work *work)
if (work->started) {
work->wpa_s->radio->num_active_works--;
wpa_dbg(work->wpa_s, MSG_DEBUG,
- "radio_work_free('%s'@%p: num_active_works --> %u",
+ "radio_work_free('%s'@%p): num_active_works --> %u",
work->type, work,
work->wpa_s->radio->num_active_works);
}
@@ -4301,6 +5154,20 @@ static void radio_work_free(struct wpa_radio_work *work)
}
+static int radio_work_is_connect(struct wpa_radio_work *work)
+{
+ return os_strcmp(work->type, "sme-connect") == 0 ||
+ os_strcmp(work->type, "connect") == 0;
+}
+
+
+static int radio_work_is_scan(struct wpa_radio_work *work)
+{
+ return os_strcmp(work->type, "scan") == 0 ||
+ os_strcmp(work->type, "p2p-scan") == 0;
+}
+
+
static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
{
struct wpa_radio_work *active_work = NULL;
@@ -4330,8 +5197,7 @@ static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
return NULL;
}
- if (os_strcmp(active_work->type, "sme-connect") == 0 ||
- os_strcmp(active_work->type, "connect") == 0) {
+ if (radio_work_is_connect(active_work)) {
/*
* If the active work is either connect or sme-connect,
* do not parallelize them with other radio works.
@@ -4350,10 +5216,20 @@ static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
* If connect or sme-connect are enqueued, parallelize only
* those operations ahead of them in the queue.
*/
- if (os_strcmp(tmp->type, "connect") == 0 ||
- os_strcmp(tmp->type, "sme-connect") == 0)
+ if (radio_work_is_connect(tmp))
break;
+ /* Serialize parallel scan and p2p_scan operations on the same
+ * interface since the driver_nl80211 mechanism for tracking
+ * scan cookies does not yet have support for this. */
+ if (active_work->wpa_s == tmp->wpa_s &&
+ radio_work_is_scan(active_work) &&
+ radio_work_is_scan(tmp)) {
+ wpa_dbg(active_work->wpa_s, MSG_DEBUG,
+ "Do not start work '%s' when another work '%s' is already scheduled",
+ tmp->type, active_work->type);
+ continue;
+ }
/*
* Check that the radio works are distinct and
* on different bands.
@@ -4475,6 +5351,22 @@ void radio_remove_works(struct wpa_supplicant *wpa_s,
}
+void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
+{
+ struct wpa_radio_work *work;
+ struct wpa_radio *radio = wpa_s->radio;
+
+ dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
+ if (work->ctx != ctx)
+ continue;
+ wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
+ work->type, work, work->started ? " (started)" : "");
+ radio_work_free(work);
+ break;
+ }
+}
+
+
static void radio_remove_interface(struct wpa_supplicant *wpa_s)
{
struct wpa_radio *radio = wpa_s->radio;
@@ -4627,7 +5519,7 @@ radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
static int wpas_init_driver(struct wpa_supplicant *wpa_s,
- struct wpa_interface *iface)
+ const struct wpa_interface *iface)
{
const char *ifname, *driver, *rn;
@@ -4675,11 +5567,47 @@ next_driver:
}
+#ifdef CONFIG_GAS_SERVER
+
+static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
+ unsigned int freq, const u8 *dst,
+ const u8 *src, const u8 *bssid,
+ const u8 *data, size_t data_len,
+ enum offchannel_send_action_result result)
+{
+ wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
+ " result=%s",
+ freq, MAC2STR(dst),
+ result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
+ (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
+ "FAILED"));
+ gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
+ result == OFFCHANNEL_SEND_ACTION_SUCCESS);
+}
+
+
+static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
+ struct wpabuf *buf, unsigned int wait_time)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+ const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+ if (wait_time > wpa_s->max_remain_on_chan)
+ wait_time = wpa_s->max_remain_on_chan;
+
+ offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
+ wpabuf_head(buf), wpabuf_len(buf),
+ wait_time, wpas_gas_server_tx_status, 0);
+}
+
+#endif /* CONFIG_GAS_SERVER */
+
static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
- struct wpa_interface *iface)
+ const struct wpa_interface *iface)
{
struct wpa_driver_capa capa;
int capa_res;
+ u8 dfs_domain;
wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
"'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
@@ -4709,7 +5637,13 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
return -1;
}
wpa_s->confanother = os_rel2abs_path(iface->confanother);
- wpa_config_read(wpa_s->confanother, wpa_s->conf);
+ if (wpa_s->confanother &&
+ !wpa_config_read(wpa_s->confanother, wpa_s->conf)) {
+ wpa_printf(MSG_ERROR,
+ "Failed to read or parse configuration '%s'.",
+ wpa_s->confanother);
+ return -1;
+ }
/*
* Override ctrl_interface and driver_param if set on command
@@ -4807,7 +5741,8 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
&wpa_s->hw.num_modes,
- &wpa_s->hw.flags);
+ &wpa_s->hw.flags,
+ &dfs_domain);
if (wpa_s->hw.modes) {
u16 i;
@@ -4858,6 +5793,12 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
capa.mac_addr_rand_sched_scan_supported)
wpa_s->mac_addr_rand_supported |=
(MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
+
+ wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
+ if (wpa_s->extended_capa &&
+ wpa_s->extended_capa_len >= 3 &&
+ wpa_s->extended_capa[2] & 0x40)
+ wpa_s->multi_bss_support = 1;
}
if (wpa_s->max_remain_on_chan == 0)
wpa_s->max_remain_on_chan = 1000;
@@ -4869,8 +5810,6 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
*/
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
wpa_s->p2p_mgmt = iface->p2p_mgmt;
- else
- iface->p2p_mgmt = 1;
if (wpa_s->num_multichan_concurrent == 0)
wpa_s->num_multichan_concurrent = 1;
@@ -4879,10 +5818,7 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
return -1;
#ifdef CONFIG_TDLS
- if ((!iface->p2p_mgmt ||
- !(wpa_s->drv_flags &
- WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
- wpa_tdls_init(wpa_s->wpa))
+ if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
return -1;
#endif /* CONFIG_TDLS */
@@ -4917,6 +5853,19 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
if (wpas_wps_init(wpa_s))
return -1;
+#ifdef CONFIG_GAS_SERVER
+ wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
+ if (!wpa_s->gas_server) {
+ wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
+ return -1;
+ }
+#endif /* CONFIG_GAS_SERVER */
+
+#ifdef CONFIG_DPP
+ if (wpas_dpp_init(wpa_s) < 0)
+ return -1;
+#endif /* CONFIG_DPP */
+
if (wpa_supplicant_init_eapol(wpa_s) < 0)
return -1;
wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
@@ -4941,7 +5890,9 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
return -1;
}
- if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
+ if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
+ wpa_s->p2p_mgmt) &&
+ wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
return -1;
}
@@ -4949,6 +5900,12 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
if (wpa_bss_init(wpa_s) < 0)
return -1;
+#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
+#ifdef CONFIG_MESH
+ dl_list_init(&wpa_s->mesh_external_pmksa_cache);
+#endif /* CONFIG_MESH */
+#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
+
/*
* Set Wake-on-WLAN triggers, if configured.
* Note: We don't restore/remove the triggers on shutdown (it doesn't
@@ -4960,8 +5917,8 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
#ifdef CONFIG_EAP_PROXY
{
size_t len;
- wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
- &len);
+ wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
+ wpa_s->imsi, &len);
if (wpa_s->mnc_len > 0) {
wpa_s->imsi[len] = '\0';
wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
@@ -4986,6 +5943,17 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
hs20_init(wpa_s);
#endif /* CONFIG_HS20 */
#ifdef CONFIG_MBO
+ if (wpa_s->conf->oce) {
+ if ((wpa_s->conf->oce & OCE_STA) &&
+ (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
+ wpa_s->enable_oce = OCE_STA;
+ if ((wpa_s->conf->oce & OCE_STA_CFON) &&
+ (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
+ /* TODO: Need to add STA-CFON support */
+ wpa_printf(MSG_ERROR,
+ "OCE STA-CFON feature is not yet supported");
+ }
+ }
wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
#endif /* CONFIG_MBO */
@@ -5250,6 +6218,7 @@ int wpa_supplicant_remove_iface(struct wpa_global *global,
#ifdef CONFIG_MESH
unsigned int mesh_if_created = wpa_s->mesh_if_created;
char *ifname = NULL;
+ struct wpa_supplicant *parent = wpa_s->parent;
#endif /* CONFIG_MESH */
/* Remove interface from the global list of interfaces */
@@ -5285,7 +6254,7 @@ int wpa_supplicant_remove_iface(struct wpa_global *global,
#ifdef CONFIG_MESH
if (mesh_if_created) {
- wpa_drv_if_remove(global->ifaces, WPA_IF_MESH, ifname);
+ wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
os_free(ifname);
}
#endif /* CONFIG_MESH */
@@ -5390,13 +6359,6 @@ struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
if (params == NULL)
return NULL;
-#ifdef CONFIG_DRIVER_NDIS
- {
- void driver_ndis_init_ops(void);
- driver_ndis_init_ops();
- }
-#endif /* CONFIG_DRIVER_NDIS */
-
#ifndef CONFIG_NO_WPA_MSG
wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
#endif /* CONFIG_NO_WPA_MSG */
@@ -5649,6 +6611,16 @@ void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
+ if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
+ struct wpa_driver_capa capa;
+ int res = wpa_drv_get_capa(wpa_s, &capa);
+
+ if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
+ wpa_printf(MSG_ERROR,
+ "Failed to update wowlan_triggers to '%s'",
+ wpa_s->conf->wowlan_triggers);
+ }
+
#ifdef CONFIG_WPS
wpas_wps_update_config(wpa_s);
#endif /* CONFIG_WPS */
@@ -5803,11 +6775,43 @@ void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
* TODO: if more than one possible AP is available in scan results,
* could try the other ones before requesting a new scan.
*/
+
+ /* speed up the connection attempt with normal scan */
+ wpa_s->normal_scans = 0;
wpa_supplicant_req_scan(wpa_s, timeout / 1000,
1000 * (timeout % 1000));
}
+#ifdef CONFIG_FILS
+void fils_connection_failure(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_ssid *ssid = wpa_s->current_ssid;
+ const u8 *realm, *username, *rrk;
+ size_t realm_len, username_len, rrk_len;
+ u16 next_seq_num;
+
+ if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
+ eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
+ &username, &username_len,
+ &realm, &realm_len, &next_seq_num,
+ &rrk, &rrk_len) != 0 ||
+ !realm)
+ return;
+
+ wpa_hexdump_ascii(MSG_DEBUG,
+ "FILS: Store last connection failure realm",
+ realm, realm_len);
+ os_free(wpa_s->last_con_fail_realm);
+ wpa_s->last_con_fail_realm = os_malloc(realm_len);
+ if (wpa_s->last_con_fail_realm) {
+ wpa_s->last_con_fail_realm_len = realm_len;
+ os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
+ }
+}
+#endif /* CONFIG_FILS */
+
+
int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
{
return wpa_s->conf->ap_scan == 2 ||
@@ -5878,6 +6882,7 @@ int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
case WPA_CTRL_REQ_SIM:
str_clear_free(eap->external_sim_resp);
eap->external_sim_resp = os_strdup(value);
+ eap->pending_req_sim = 0;
break;
case WPA_CTRL_REQ_PSK_PASSPHRASE:
if (wpa_config_set(ssid, "psk", value, 0) < 0)
@@ -5946,6 +6951,7 @@ int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
(!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
+ !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
!ssid->mem_only_psk)
return 1;
@@ -6130,6 +7136,7 @@ void wpas_request_connection(struct wpa_supplicant *wpa_s)
wpa_s->extra_blacklist_count = 0;
wpa_s->disconnected = 0;
wpa_s->reassociate = 1;
+ wpa_s->last_owe_group = 0;
if (wpa_supplicant_fast_associate(wpa_s) != 1)
wpa_supplicant_req_scan(wpa_s, 0, 0);
@@ -6156,6 +7163,8 @@ void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
wpa_supplicant_cancel_scan(wpa_s);
wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
+ radio_remove_works(wpa_s, "connect", 0);
+ radio_remove_works(wpa_s, "sme-connect", 0);
}
@@ -6256,489 +7265,6 @@ int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
}
-static void wpas_rrm_neighbor_rep_timeout_handler(void *data, void *user_ctx)
-{
- struct rrm_data *rrm = data;
-
- if (!rrm->notify_neighbor_rep) {
- wpa_printf(MSG_ERROR,
- "RRM: Unexpected neighbor report timeout");
- return;
- }
-
- wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report - NONE");
- rrm->notify_neighbor_rep(rrm->neighbor_rep_cb_ctx, NULL);
-
- rrm->notify_neighbor_rep = NULL;
- rrm->neighbor_rep_cb_ctx = NULL;
-}
-
-
-/*
- * wpas_rrm_reset - Clear and reset all RRM data in wpa_supplicant
- * @wpa_s: Pointer to wpa_supplicant
- */
-void wpas_rrm_reset(struct wpa_supplicant *wpa_s)
-{
- wpa_s->rrm.rrm_used = 0;
-
- eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
- NULL);
- if (wpa_s->rrm.notify_neighbor_rep)
- wpas_rrm_neighbor_rep_timeout_handler(&wpa_s->rrm, NULL);
- wpa_s->rrm.next_neighbor_rep_token = 1;
-}
-
-
-/*
- * wpas_rrm_process_neighbor_rep - Handle incoming neighbor report
- * @wpa_s: Pointer to wpa_supplicant
- * @report: Neighbor report buffer, prefixed by a 1-byte dialog token
- * @report_len: Length of neighbor report buffer
- */
-void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s,
- const u8 *report, size_t report_len)
-{
- struct wpabuf *neighbor_rep;
-
- wpa_hexdump(MSG_DEBUG, "RRM: New Neighbor Report", report, report_len);
- if (report_len < 1)
- return;
-
- if (report[0] != wpa_s->rrm.next_neighbor_rep_token - 1) {
- wpa_printf(MSG_DEBUG,
- "RRM: Discarding neighbor report with token %d (expected %d)",
- report[0], wpa_s->rrm.next_neighbor_rep_token - 1);
- return;
- }
-
- eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
- NULL);
-
- if (!wpa_s->rrm.notify_neighbor_rep) {
- wpa_printf(MSG_ERROR, "RRM: Unexpected neighbor report");
- return;
- }
-
- /* skipping the first byte, which is only an id (dialog token) */
- neighbor_rep = wpabuf_alloc(report_len - 1);
- if (neighbor_rep == NULL)
- return;
- wpabuf_put_data(neighbor_rep, report + 1, report_len - 1);
- wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report (token = %d)",
- report[0]);
- wpa_s->rrm.notify_neighbor_rep(wpa_s->rrm.neighbor_rep_cb_ctx,
- neighbor_rep);
- wpa_s->rrm.notify_neighbor_rep = NULL;
- wpa_s->rrm.neighbor_rep_cb_ctx = NULL;
-}
-
-
-#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS)
-/* Workaround different, undefined for Windows, error codes used here */
-#define ENOTCONN -1
-#define EOPNOTSUPP -1
-#define ECANCELED -1
-#endif
-
-/* Measurement Request element + Location Subject + Maximum Age subelement */
-#define MEASURE_REQUEST_LCI_LEN (3 + 1 + 4)
-/* Measurement Request element + Location Civic Request */
-#define MEASURE_REQUEST_CIVIC_LEN (3 + 5)
-
-
-/**
- * wpas_rrm_send_neighbor_rep_request - Request a neighbor report from our AP
- * @wpa_s: Pointer to wpa_supplicant
- * @ssid: if not null, this is sent in the request. Otherwise, no SSID IE
- * is sent in the request.
- * @lci: if set, neighbor request will include LCI request
- * @civic: if set, neighbor request will include civic location request
- * @cb: Callback function to be called once the requested report arrives, or
- * timed out after RRM_NEIGHBOR_REPORT_TIMEOUT seconds.
- * In the former case, 'neighbor_rep' is a newly allocated wpabuf, and it's
- * the requester's responsibility to free it.
- * In the latter case NULL will be sent in 'neighbor_rep'.
- * @cb_ctx: Context value to send the callback function
- * Returns: 0 in case of success, negative error code otherwise
- *
- * In case there is a previous request which has not been answered yet, the
- * new request fails. The caller may retry after RRM_NEIGHBOR_REPORT_TIMEOUT.
- * Request must contain a callback function.
- */
-int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
- const struct wpa_ssid_value *ssid,
- int lci, int civic,
- void (*cb)(void *ctx,
- struct wpabuf *neighbor_rep),
- void *cb_ctx)
-{
- struct wpabuf *buf;
- const u8 *rrm_ie;
-
- if (wpa_s->wpa_state != WPA_COMPLETED || wpa_s->current_ssid == NULL) {
- wpa_printf(MSG_DEBUG, "RRM: No connection, no RRM.");
- return -ENOTCONN;
- }
-
- if (!wpa_s->rrm.rrm_used) {
- wpa_printf(MSG_DEBUG, "RRM: No RRM in current connection.");
- return -EOPNOTSUPP;
- }
-
- rrm_ie = wpa_bss_get_ie(wpa_s->current_bss,
- WLAN_EID_RRM_ENABLED_CAPABILITIES);
- if (!rrm_ie || !(wpa_s->current_bss->caps & IEEE80211_CAP_RRM) ||
- !(rrm_ie[2] & WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
- wpa_printf(MSG_DEBUG,
- "RRM: No network support for Neighbor Report.");
- return -EOPNOTSUPP;
- }
-
- if (!cb) {
- wpa_printf(MSG_DEBUG,
- "RRM: Neighbor Report request must provide a callback.");
- return -EINVAL;
- }
-
- /* Refuse if there's a live request */
- if (wpa_s->rrm.notify_neighbor_rep) {
- wpa_printf(MSG_DEBUG,
- "RRM: Currently handling previous Neighbor Report.");
- return -EBUSY;
- }
-
- /* 3 = action category + action code + dialog token */
- buf = wpabuf_alloc(3 + (ssid ? 2 + ssid->ssid_len : 0) +
- (lci ? 2 + MEASURE_REQUEST_LCI_LEN : 0) +
- (civic ? 2 + MEASURE_REQUEST_CIVIC_LEN : 0));
- if (buf == NULL) {
- wpa_printf(MSG_DEBUG,
- "RRM: Failed to allocate Neighbor Report Request");
- return -ENOMEM;
- }
-
- wpa_printf(MSG_DEBUG, "RRM: Neighbor report request (for %s), token=%d",
- (ssid ? wpa_ssid_txt(ssid->ssid, ssid->ssid_len) : ""),
- wpa_s->rrm.next_neighbor_rep_token);
-
- wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
- wpabuf_put_u8(buf, WLAN_RRM_NEIGHBOR_REPORT_REQUEST);
- wpabuf_put_u8(buf, wpa_s->rrm.next_neighbor_rep_token);
- if (ssid) {
- wpabuf_put_u8(buf, WLAN_EID_SSID);
- wpabuf_put_u8(buf, ssid->ssid_len);
- wpabuf_put_data(buf, ssid->ssid, ssid->ssid_len);
- }
-
- if (lci) {
- /* IEEE P802.11-REVmc/D5.0 9.4.2.21 */
- wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST);
- wpabuf_put_u8(buf, MEASURE_REQUEST_LCI_LEN);
-
- /*
- * Measurement token; nonzero number that is unique among the
- * Measurement Request elements in a particular frame.
- */
- wpabuf_put_u8(buf, 1); /* Measurement Token */
-
- /*
- * Parallel, Enable, Request, and Report bits are 0, Duration is
- * reserved.
- */
- wpabuf_put_u8(buf, 0); /* Measurement Request Mode */
- wpabuf_put_u8(buf, MEASURE_TYPE_LCI); /* Measurement Type */
-
- /* IEEE P802.11-REVmc/D5.0 9.4.2.21.10 - LCI request */
- /* Location Subject */
- wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE);
-
- /* Optional Subelements */
- /*
- * IEEE P802.11-REVmc/D5.0 Figure 9-170
- * The Maximum Age subelement is required, otherwise the AP can
- * send only data that was determined after receiving the
- * request. Setting it here to unlimited age.
- */
- wpabuf_put_u8(buf, LCI_REQ_SUBELEM_MAX_AGE);
- wpabuf_put_u8(buf, 2);
- wpabuf_put_le16(buf, 0xffff);
- }
-
- if (civic) {
- /* IEEE P802.11-REVmc/D5.0 9.4.2.21 */
- wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST);
- wpabuf_put_u8(buf, MEASURE_REQUEST_CIVIC_LEN);
-
- /*
- * Measurement token; nonzero number that is unique among the
- * Measurement Request elements in a particular frame.
- */
- wpabuf_put_u8(buf, 2); /* Measurement Token */
-
- /*
- * Parallel, Enable, Request, and Report bits are 0, Duration is
- * reserved.
- */
- wpabuf_put_u8(buf, 0); /* Measurement Request Mode */
- /* Measurement Type */
- wpabuf_put_u8(buf, MEASURE_TYPE_LOCATION_CIVIC);
-
- /* IEEE P802.11-REVmc/D5.0 9.4.2.21.14:
- * Location Civic request */
- /* Location Subject */
- wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE);
- wpabuf_put_u8(buf, 0); /* Civic Location Type: IETF RFC 4776 */
- /* Location Service Interval Units: Seconds */
- wpabuf_put_u8(buf, 0);
- /* Location Service Interval: 0 - Only one report is requested
- */
- wpabuf_put_le16(buf, 0);
- /* No optional subelements */
- }
-
- wpa_s->rrm.next_neighbor_rep_token++;
-
- if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
- wpa_s->own_addr, wpa_s->bssid,
- wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
- wpa_printf(MSG_DEBUG,
- "RRM: Failed to send Neighbor Report Request");
- wpabuf_free(buf);
- return -ECANCELED;
- }
-
- wpa_s->rrm.neighbor_rep_cb_ctx = cb_ctx;
- wpa_s->rrm.notify_neighbor_rep = cb;
- eloop_register_timeout(RRM_NEIGHBOR_REPORT_TIMEOUT, 0,
- wpas_rrm_neighbor_rep_timeout_handler,
- &wpa_s->rrm, NULL);
-
- wpabuf_free(buf);
- return 0;
-}
-
-
-static struct wpabuf * wpas_rrm_build_lci_report(struct wpa_supplicant *wpa_s,
- const u8 *request, size_t len,
- struct wpabuf *report)
-{
- u8 token, type, subject;
- u16 max_age = 0;
- struct os_reltime t, diff;
- unsigned long diff_l;
- u8 *ptoken;
- const u8 *subelem;
-
- if (!wpa_s->lci || len < 3 + 4)
- return report;
-
- token = *request++;
- /* Measurement request mode isn't used */
- request++;
- type = *request++;
- subject = *request++;
-
- wpa_printf(MSG_DEBUG,
- "Measurement request token %u type %u location subject %u",
- token, type, subject);
-
- if (type != MEASURE_TYPE_LCI || subject != LOCATION_SUBJECT_REMOTE) {
- wpa_printf(MSG_INFO,
- "Not building LCI report - bad type or location subject");
- return report;
- }
-
- /* Subelements are formatted exactly like elements */
- subelem = get_ie(request, len, LCI_REQ_SUBELEM_MAX_AGE);
- if (subelem && subelem[1] == 2)
- max_age = WPA_GET_LE16(subelem + 2);
-
- if (os_get_reltime(&t))
- return report;
-
- os_reltime_sub(&t, &wpa_s->lci_time, &diff);
- /* LCI age is calculated in 10th of a second units. */
- diff_l = diff.sec * 10 + diff.usec / 100000;
-
- if (max_age != 0xffff && max_age < diff_l)
- return report;
-
- if (wpabuf_resize(&report, 2 + wpabuf_len(wpa_s->lci)))
- return report;
-
- wpabuf_put_u8(report, WLAN_EID_MEASURE_REPORT);
- wpabuf_put_u8(report, wpabuf_len(wpa_s->lci));
- /* We'll override user's measurement token */
- ptoken = wpabuf_put(report, 0);
- wpabuf_put_buf(report, wpa_s->lci);
- *ptoken = token;
-
- return report;
-}
-
-
-void wpas_rrm_handle_radio_measurement_request(struct wpa_supplicant *wpa_s,
- const u8 *src,
- const u8 *frame, size_t len)
-{
- struct wpabuf *buf, *report;
- u8 token;
- const u8 *ie, *end;
-
- if (wpa_s->wpa_state != WPA_COMPLETED) {
- wpa_printf(MSG_INFO,
- "RRM: Ignoring radio measurement request: Not associated");
- return;
- }
-
- if (!wpa_s->rrm.rrm_used) {
- wpa_printf(MSG_INFO,
- "RRM: Ignoring radio measurement request: Not RRM network");
- return;
- }
-
- if (len < 3) {
- wpa_printf(MSG_INFO,
- "RRM: Ignoring too short radio measurement request");
- return;
- }
-
- end = frame + len;
-
- token = *frame++;
-
- /* Ignore number of repetitions because it's not used in LCI request */
- frame += 2;
-
- report = NULL;
- while ((ie = get_ie(frame, end - frame, WLAN_EID_MEASURE_REQUEST)) &&
- ie[1] >= 3) {
- u8 msmt_type;
-
- msmt_type = ie[4];
- wpa_printf(MSG_DEBUG, "RRM request %d", msmt_type);
-
- switch (msmt_type) {
- case MEASURE_TYPE_LCI:
- report = wpas_rrm_build_lci_report(wpa_s, ie + 2, ie[1],
- report);
- break;
- default:
- wpa_printf(MSG_INFO,
- "RRM: Unsupported radio measurement request %d",
- msmt_type);
- break;
- }
-
- frame = ie + ie[1] + 2;
- }
-
- if (!report)
- return;
-
- buf = wpabuf_alloc(3 + wpabuf_len(report));
- if (!buf) {
- wpabuf_free(report);
- return;
- }
-
- wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
- wpabuf_put_u8(buf, WLAN_RRM_RADIO_MEASUREMENT_REPORT);
- wpabuf_put_u8(buf, token);
-
- wpabuf_put_buf(buf, report);
- wpabuf_free(report);
-
- if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src,
- wpa_s->own_addr, wpa_s->bssid,
- wpabuf_head(buf), wpabuf_len(buf), 0)) {
- wpa_printf(MSG_ERROR,
- "RRM: Radio measurement report failed: Sending Action frame failed");
- }
- wpabuf_free(buf);
-}
-
-
-void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s,
- const u8 *src,
- const u8 *frame, size_t len,
- int rssi)
-{
- struct wpabuf *buf;
- const struct rrm_link_measurement_request *req;
- struct rrm_link_measurement_report report;
-
- if (wpa_s->wpa_state != WPA_COMPLETED) {
- wpa_printf(MSG_INFO,
- "RRM: Ignoring link measurement request. Not associated");
- return;
- }
-
- if (!wpa_s->rrm.rrm_used) {
- wpa_printf(MSG_INFO,
- "RRM: Ignoring link measurement request. Not RRM network");
- return;
- }
-
- if (!(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)) {
- wpa_printf(MSG_INFO,
- "RRM: Measurement report failed. TX power insertion not supported");
- return;
- }
-
- req = (const struct rrm_link_measurement_request *) frame;
- if (len < sizeof(*req)) {
- wpa_printf(MSG_INFO,
- "RRM: Link measurement report failed. Request too short");
- return;
- }
-
- os_memset(&report, 0, sizeof(report));
- report.tpc.eid = WLAN_EID_TPC_REPORT;
- report.tpc.len = 2;
- report.rsni = 255; /* 255 indicates that RSNI is not available */
- report.dialog_token = req->dialog_token;
-
- /*
- * It's possible to estimate RCPI based on RSSI in dBm. This
- * calculation will not reflect the correct value for high rates,
- * but it's good enough for Action frames which are transmitted
- * with up to 24 Mbps rates.
- */
- if (!rssi)
- report.rcpi = 255; /* not available */
- else if (rssi < -110)
- report.rcpi = 0;
- else if (rssi > 0)
- report.rcpi = 220;
- else
- report.rcpi = (rssi + 110) * 2;
-
- /* action_category + action_code */
- buf = wpabuf_alloc(2 + sizeof(report));
- if (buf == NULL) {
- wpa_printf(MSG_ERROR,
- "RRM: Link measurement report failed. Buffer allocation failed");
- return;
- }
-
- wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
- wpabuf_put_u8(buf, WLAN_RRM_LINK_MEASUREMENT_REPORT);
- wpabuf_put_data(buf, &report, sizeof(report));
- wpa_hexdump(MSG_DEBUG, "RRM: Link measurement report:",
- wpabuf_head(buf), wpabuf_len(buf));
-
- if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src,
- wpa_s->own_addr, wpa_s->bssid,
- wpabuf_head(buf), wpabuf_len(buf), 0)) {
- wpa_printf(MSG_ERROR,
- "RRM: Link measurement report failed. Send action failed");
- }
- wpabuf_free(buf);
-}
-
-
struct wpa_supplicant *
wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
{
@@ -6852,19 +7378,55 @@ wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
}
+static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_bss_tmp_disallowed *tmp;
+ unsigned int num_bssid = 0;
+ u8 *bssids;
+ int ret;
+
+ bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
+ if (!bssids)
+ return -1;
+ dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
+ struct wpa_bss_tmp_disallowed, list) {
+ os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
+ ETH_ALEN);
+ num_bssid++;
+ }
+ ret = wpa_drv_set_bssid_blacklist(wpa_s, num_bssid, bssids);
+ os_free(bssids);
+ return ret;
+}
+
+
+static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
+{
+ struct wpa_supplicant *wpa_s = eloop_ctx;
+ struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
+
+ /* Make sure the bss is not already freed */
+ dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
+ struct wpa_bss_tmp_disallowed, list) {
+ if (bss == tmp) {
+ dl_list_del(&tmp->list);
+ os_free(tmp);
+ wpa_set_driver_tmp_disallow_list(wpa_s);
+ break;
+ }
+ }
+}
+
+
void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
- unsigned int sec)
+ unsigned int sec, int rssi_threshold)
{
struct wpa_bss_tmp_disallowed *bss;
- struct os_reltime until;
-
- os_get_reltime(&until);
- until.sec += sec;
bss = wpas_get_disallowed_bss(wpa_s, bssid);
if (bss) {
- bss->disallowed_until = until;
- return;
+ eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
+ goto finish;
}
bss = os_malloc(sizeof(*bss));
@@ -6874,38 +7436,35 @@ void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
return;
}
- bss->disallowed_until = until;
os_memcpy(bss->bssid, bssid, ETH_ALEN);
dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
+ wpa_set_driver_tmp_disallow_list(wpa_s);
+
+finish:
+ bss->rssi_threshold = rssi_threshold;
+ eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
+ wpa_s, bss);
}
-int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s, const u8 *bssid)
+int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
+ struct wpa_bss *bss)
{
- struct wpa_bss_tmp_disallowed *bss = NULL, *tmp, *prev;
- struct os_reltime now, age;
-
- os_get_reltime(&now);
+ struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
struct wpa_bss_tmp_disallowed, list) {
- if (!os_reltime_before(&now, &tmp->disallowed_until)) {
- /* This BSS is not disallowed anymore */
- dl_list_del(&tmp->list);
- os_free(tmp);
- continue;
- }
- if (os_memcmp(bssid, tmp->bssid, ETH_ALEN) == 0) {
- bss = tmp;
+ if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
+ disallowed = tmp;
break;
}
}
- if (!bss)
+ if (!disallowed)
+ return 0;
+
+ if (disallowed->rssi_threshold != 0 &&
+ bss->level > disallowed->rssi_threshold)
return 0;
- os_reltime_sub(&bss->disallowed_until, &now, &age);
- wpa_printf(MSG_DEBUG,
- "BSS " MACSTR " disabled for %ld.%0ld seconds",
- MAC2STR(bss->bssid), age.sec, age.usec);
return 1;
}
diff --git a/freebsd/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h b/freebsd/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h
index ef9273d0..16e4db62 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h
@@ -9,6 +9,7 @@
#ifndef WPA_SUPPLICANT_I_H
#define WPA_SUPPLICANT_I_H
+#include "utils/bitfield.h"
#include "utils/list.h"
#include "common/defs.h"
#include "common/sae.h"
@@ -295,7 +296,7 @@ struct wpa_global {
#ifdef CONFIG_WIFI_DISPLAY
int wifi_display;
-#define MAX_WFD_SUBELEMS 10
+#define MAX_WFD_SUBELEMS 12
struct wpabuf *wfd_subelem[MAX_WFD_SUBELEMS];
#endif /* CONFIG_WIFI_DISPLAY */
@@ -344,6 +345,7 @@ int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
void radio_work_done(struct wpa_radio_work *work);
void radio_remove_works(struct wpa_supplicant *wpa_s,
const char *type, int remove_all);
+void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx);
void radio_work_check_next(struct wpa_supplicant *wpa_s);
struct wpa_radio_work *
radio_work_pending(struct wpa_supplicant *wpa_s, const char *type);
@@ -424,6 +426,12 @@ struct rrm_data {
/* next_neighbor_rep_token - Next request's dialog token */
u8 next_neighbor_rep_token;
+
+ /* token - Dialog token of the current radio measurement */
+ u8 token;
+
+ /* destination address of the current radio measurement request */
+ u8 dst_addr[ETH_ALEN];
};
enum wpa_supplicant_test_failure {
@@ -443,7 +451,30 @@ struct icon_entry {
struct wpa_bss_tmp_disallowed {
struct dl_list list;
u8 bssid[ETH_ALEN];
- struct os_reltime disallowed_until;
+ int rssi_threshold;
+};
+
+struct beacon_rep_data {
+ u8 token;
+ u8 last_indication;
+ struct wpa_driver_scan_params scan_params;
+ u8 ssid[SSID_MAX_LEN];
+ size_t ssid_len;
+ u8 bssid[ETH_ALEN];
+ enum beacon_report_detail report_detail;
+ struct bitfield *eids;
+};
+
+
+struct external_pmksa_cache {
+ struct dl_list list;
+ void *pmksa_cache;
+};
+
+struct fils_hlp_req {
+ struct dl_list list;
+ u8 dst[ETH_ALEN];
+ struct wpabuf *pkt;
};
/**
@@ -463,15 +494,16 @@ struct wpa_supplicant {
struct wpa_supplicant *next;
struct l2_packet_data *l2;
struct l2_packet_data *l2_br;
+ struct os_reltime roam_start;
+ struct os_reltime roam_time;
+ struct os_reltime session_start;
+ struct os_reltime session_length;
unsigned char own_addr[ETH_ALEN];
unsigned char perm_addr[ETH_ALEN];
char ifname[100];
#ifdef CONFIG_MATCH_IFACE
int matched;
#endif /* CONFIG_MATCH_IFACE */
-#ifdef CONFIG_CTRL_IFACE_DBUS
- char *dbus_path;
-#endif /* CONFIG_CTRL_IFACE_DBUS */
#ifdef CONFIG_CTRL_IFACE_DBUS_NEW
char *dbus_new_path;
char *dbus_groupobj_path;
@@ -503,6 +535,8 @@ struct wpa_supplicant {
struct wpa_bss *current_bss;
int ap_ies_from_associnfo;
unsigned int assoc_freq;
+ u8 *last_con_fail_realm;
+ size_t last_con_fail_realm_len;
/* Selected configuration (based on Beacon/ProbeResp WPA IE) */
int pairwise_cipher;
@@ -639,6 +673,7 @@ struct wpa_supplicant {
struct os_reltime scan_min_time;
int scan_runs; /* number of scan runs since WPS was started */
int *next_scan_freqs;
+ int *select_network_scan_freqs;
int *manual_scan_freqs;
int *manual_sched_scan_freqs;
unsigned int manual_scan_passive:1;
@@ -652,6 +687,12 @@ struct wpa_supplicant {
int normal_scans; /* normal scans run before sched_scan */
int scan_for_connection; /* whether the scan request was triggered for
* finding a connection */
+ /*
+ * A unique cookie representing the vendor scan request. This cookie is
+ * returned from the driver interface. 0 indicates that there is no
+ * pending vendor scan request.
+ */
+ u64 curr_scan_cookie;
#define MAX_SCAN_ID 16
int scan_id[MAX_SCAN_ID];
unsigned int scan_id_count;
@@ -705,6 +746,12 @@ struct wpa_supplicant {
unsigned int mac_addr_changed:1;
unsigned int added_vif:1;
unsigned int wnmsleep_used:1;
+ unsigned int owe_transition_select:1;
+ unsigned int owe_transition_search:1;
+ unsigned int connection_set:1;
+ unsigned int connection_ht:1;
+ unsigned int connection_vht:1;
+ unsigned int connection_he:1;
struct os_reltime last_mac_addr_change;
int last_mac_addr_style;
@@ -715,13 +762,15 @@ struct wpa_supplicant {
int sta_uapsd;
int set_ap_uapsd;
int ap_uapsd;
+ int auth_alg;
+ u16 last_owe_group;
#ifdef CONFIG_SME
struct {
u8 ssid[SSID_MAX_LEN];
size_t ssid_len;
int freq;
- u8 assoc_req_ie[200];
+ u8 assoc_req_ie[1500];
size_t assoc_req_ie_len;
int mfp;
int ft_used;
@@ -752,6 +801,8 @@ struct wpa_supplicant {
struct wpabuf *sae_token;
int sae_group_index;
unsigned int sae_pmksa_caching:1;
+ u16 seq_num;
+ struct external_auth ext_auth;
#endif /* CONFIG_SAE */
} sme;
#endif /* CONFIG_SME */
@@ -770,6 +821,11 @@ struct wpa_supplicant {
unsigned int mesh_if_created:1;
unsigned int mesh_ht_enabled:1;
unsigned int mesh_vht_enabled:1;
+ struct wpa_driver_mesh_join_params *mesh_params;
+#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
+ /* struct external_pmksa_cache::list */
+ struct dl_list mesh_external_pmksa_cache;
+#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
#endif /* CONFIG_MESH */
unsigned int off_channel_freq;
@@ -789,6 +845,7 @@ struct wpa_supplicant {
result);
unsigned int roc_waiting_drv_freq;
int action_tx_wait_time;
+ int action_tx_wait_time_used;
int p2p_mgmt;
@@ -856,11 +913,13 @@ struct wpa_supplicant {
unsigned int p2p_auto_join:1;
unsigned int p2p_auto_pd:1;
+ unsigned int p2p_go_do_acs:1;
unsigned int p2p_persistent_group:1;
unsigned int p2p_fallback_to_go_neg:1;
unsigned int p2p_pd_before_go_neg:1;
unsigned int p2p_go_ht40:1;
unsigned int p2p_go_vht:1;
+ unsigned int p2p_go_he:1;
unsigned int user_initiated_pd:1;
unsigned int p2p_go_group_formation_completed:1;
unsigned int group_formation_reported:1;
@@ -871,6 +930,7 @@ struct wpa_supplicant {
unsigned int p2p_disable_ip_addr_req:1;
unsigned int p2ps_method_config_any:1;
unsigned int p2p_cli_probe:1;
+ enum hostapd_hw_mode p2p_go_acs_band;
int p2p_persistent_go_freq;
int p2p_persistent_id;
int p2p_go_intent;
@@ -923,6 +983,7 @@ struct wpa_supplicant {
int best_overall_freq;
struct gas_query *gas;
+ struct gas_server *gas_server;
#ifdef CONFIG_INTERWORKING
unsigned int fetch_anqp_in_progress:1;
@@ -966,6 +1027,10 @@ struct wpa_supplicant {
/* WLAN_REASON_* reason codes. Negative if locally generated. */
int disconnect_reason;
+ /* WLAN_STATUS_* status codes from last received Authentication frame
+ * from the AP. */
+ u16 auth_status_code;
+
/* WLAN_STATUS_* status codes from (Re)Association Response frame. */
u16 assoc_status_code;
@@ -981,6 +1046,7 @@ struct wpa_supplicant {
unsigned int wmm_ac_supported:1;
unsigned int ext_work_in_progress:1;
unsigned int own_disconnect_req:1;
+ unsigned int ignore_post_flush_scan_res:1;
#define MAC_ADDR_RAND_SCAN BIT(0)
#define MAC_ADDR_RAND_SCHED_SCAN BIT(1)
@@ -1006,6 +1072,15 @@ struct wpa_supplicant {
struct neighbor_report *wnm_neighbor_report_elements;
struct os_reltime wnm_cand_valid_until;
u8 wnm_cand_from_bss[ETH_ALEN];
+ enum bss_trans_mgmt_status_code bss_tm_status;
+ struct wpabuf *coloc_intf_elems;
+ u8 coloc_intf_dialog_token;
+ u8 coloc_intf_auto_report;
+ u8 coloc_intf_timeout;
+#ifdef CONFIG_MBO
+ unsigned int wnm_mbo_trans_reason_present:1;
+ u8 wnm_mbo_transition_reason;
+#endif /* CONFIG_MBO */
#endif /* CONFIG_WNM */
#ifdef CONFIG_TESTING_GET_GTK
@@ -1024,10 +1099,19 @@ struct wpa_supplicant {
struct l2_packet_data *l2_test;
unsigned int extra_roc_dur;
enum wpa_supplicant_test_failure test_failure;
+ char *get_pref_freq_list_override;
unsigned int reject_btm_req_reason;
unsigned int p2p_go_csa_on_inv:1;
unsigned int ignore_auth_resp:1;
unsigned int ignore_assoc_disallow:1;
+ unsigned int testing_resend_assoc:1;
+ struct wpabuf *sae_commit_override;
+ enum wpa_alg last_tk_alg;
+ u8 last_tk_addr[ETH_ALEN];
+ int last_tk_key_idx;
+ u8 last_tk[WPA_TK_MAX_LEN];
+ size_t last_tk_len;
+ struct wpabuf *last_assoc_req_wpa_ie;
#endif /* CONFIG_TESTING_OPTIONS */
struct wmm_ac_assoc_data *wmm_ac_assoc_info;
@@ -1038,6 +1122,7 @@ struct wpa_supplicant {
u8 last_tspecs_count;
struct rrm_data rrm;
+ struct beacon_rep_data beacon_rep_data;
#ifdef CONFIG_FST
struct fst_iface *fst;
@@ -1055,6 +1140,14 @@ struct wpa_supplicant {
} *non_pref_chan;
size_t non_pref_chan_num;
u8 mbo_wnm_token;
+ /**
+ * enable_oce - Enable OCE if it is enabled by user and device also
+ * supports OCE.
+ * User can enable OCE with wpa_config's 'oce' parameter as follows -
+ * - Set BIT(0) to enable OCE in non-AP STA mode.
+ * - Set BIT(1) to enable OCE in STA-CFON mode.
+ */
+ u8 enable_oce;
#endif /* CONFIG_MBO */
/*
@@ -1069,6 +1162,95 @@ struct wpa_supplicant {
*/
struct wpabuf *lci;
struct os_reltime lci_time;
+
+ struct os_reltime beacon_rep_scan;
+
+ /* FILS HLP requests (struct fils_hlp_req) */
+ struct dl_list fils_hlp_req;
+
+ struct sched_scan_relative_params {
+ /**
+ * relative_rssi_set - Enable relatively preferred BSS reporting
+ *
+ * 0 = Disable reporting relatively preferred BSSs
+ * 1 = Enable reporting relatively preferred BSSs
+ */
+ int relative_rssi_set;
+
+ /**
+ * relative_rssi - Relative RSSI for reporting better BSSs
+ *
+ * Amount of RSSI by which a BSS should be better than the
+ * current connected BSS so that the new BSS can be reported
+ * to user space. This applies to sched_scan operations.
+ */
+ int relative_rssi;
+
+ /**
+ * relative_adjust_band - Band in which RSSI is to be adjusted
+ */
+ enum set_band relative_adjust_band;
+
+ /**
+ * relative_adjust_rssi - RSSI adjustment
+ *
+ * An amount of relative_adjust_rssi should be added to the
+ * BSSs that belong to the relative_adjust_band while comparing
+ * with other bands for BSS reporting.
+ */
+ int relative_adjust_rssi;
+ } srp;
+
+ /* RIC elements for FT protocol */
+ struct wpabuf *ric_ies;
+
+ int last_auth_timeout_sec;
+
+#ifdef CONFIG_DPP
+ struct dpp_global *dpp;
+ struct dpp_authentication *dpp_auth;
+ struct wpa_radio_work *dpp_listen_work;
+ unsigned int dpp_pending_listen_freq;
+ unsigned int dpp_listen_freq;
+ u8 dpp_allowed_roles;
+ int dpp_qr_mutual;
+ int dpp_netrole_ap;
+ int dpp_auth_ok_on_ack;
+ int dpp_in_response_listen;
+ int dpp_gas_client;
+ int dpp_gas_dialog_token;
+ u8 dpp_intro_bssid[ETH_ALEN];
+ void *dpp_intro_network;
+ struct dpp_pkex *dpp_pkex;
+ struct dpp_bootstrap_info *dpp_pkex_bi;
+ char *dpp_pkex_code;
+ char *dpp_pkex_identifier;
+ char *dpp_pkex_auth_cmd;
+ char *dpp_configurator_params;
+ struct os_reltime dpp_last_init;
+ struct os_reltime dpp_init_iter_start;
+ unsigned int dpp_init_max_tries;
+ unsigned int dpp_init_retry_time;
+ unsigned int dpp_resp_wait_time;
+ unsigned int dpp_resp_max_tries;
+ unsigned int dpp_resp_retry_time;
+#ifdef CONFIG_DPP2
+ struct dpp_pfs *dpp_pfs;
+#endif /* CONFIG_DPP2 */
+#ifdef CONFIG_TESTING_OPTIONS
+ char *dpp_config_obj_override;
+ char *dpp_discovery_override;
+ char *dpp_groups_override;
+ unsigned int dpp_ignore_netaccesskey_mismatch:1;
+#endif /* CONFIG_TESTING_OPTIONS */
+#endif /* CONFIG_DPP */
+
+#ifdef CONFIG_FILS
+ unsigned int disable_fils:1;
+#endif /* CONFIG_FILS */
+ unsigned int ieee80211ac:1;
+ unsigned int enabled_4addr_mode:1;
+ unsigned int multi_bss_support:1;
};
@@ -1101,6 +1283,7 @@ void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s);
void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr);
void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
int sec, int usec);
+void wpas_auth_timeout_restart(struct wpa_supplicant *wpa_s, int sec_diff);
void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s);
void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
enum wpa_states state);
@@ -1158,6 +1341,7 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s);
void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s);
void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid);
+void fils_connection_failure(struct wpa_supplicant *wpa_s);
int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s);
int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s);
void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason);
@@ -1183,22 +1367,30 @@ int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
struct wpabuf *neighbor_rep),
void *cb_ctx);
void wpas_rrm_handle_radio_measurement_request(struct wpa_supplicant *wpa_s,
- const u8 *src,
+ const u8 *src, const u8 *dst,
const u8 *frame, size_t len);
void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s,
const u8 *src,
const u8 *frame, size_t len,
int rssi);
+void wpas_rrm_refuse_request(struct wpa_supplicant *wpa_s);
+int wpas_beacon_rep_scan_process(struct wpa_supplicant *wpa_s,
+ struct wpa_scan_results *scan_res,
+ struct scan_info *info);
+void wpas_clear_beacon_rep_data(struct wpa_supplicant *wpa_s);
+void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s);
/* MBO functions */
-int wpas_mbo_ie(struct wpa_supplicant *wpa_s, u8 *buf, size_t len);
+int wpas_mbo_ie(struct wpa_supplicant *wpa_s, u8 *buf, size_t len,
+ int add_oce_capa);
+const u8 * mbo_attr_from_mbo_ie(const u8 *mbo_ie, enum mbo_attr_id attr);
const u8 * wpas_mbo_get_bss_attr(struct wpa_bss *bss, enum mbo_attr_id attr);
+const u8 * mbo_get_attr_from_ies(const u8 *ies, size_t ies_len,
+ enum mbo_attr_id attr);
int wpas_mbo_update_non_pref_chan(struct wpa_supplicant *wpa_s,
const char *non_pref_chan);
void wpas_mbo_scan_ie(struct wpa_supplicant *wpa_s, struct wpabuf *ie);
-int wpas_mbo_supp_op_class_ie(struct wpa_supplicant *wpa_s, int freq, u8 *pos,
- size_t len);
void wpas_mbo_ie_trans_req(struct wpa_supplicant *wpa_s, const u8 *ie,
size_t len);
size_t wpas_mbo_ie_bss_trans_reject(struct wpa_supplicant *wpa_s, u8 *pos,
@@ -1206,7 +1398,22 @@ size_t wpas_mbo_ie_bss_trans_reject(struct wpa_supplicant *wpa_s, u8 *pos,
enum mbo_transition_reject_reason reason);
void wpas_mbo_update_cell_capa(struct wpa_supplicant *wpa_s, u8 mbo_cell_capa);
struct wpabuf * mbo_build_anqp_buf(struct wpa_supplicant *wpa_s,
- struct wpa_bss *bss);
+ struct wpa_bss *bss, u32 mbo_subtypes);
+void mbo_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
+ struct wpa_bss *bss, const u8 *sa,
+ const u8 *data, size_t slen);
+void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s);
+
+/* op_classes.c */
+enum chan_allowed {
+ NOT_ALLOWED, NO_IR, ALLOWED
+};
+
+enum chan_allowed verify_channel(struct hostapd_hw_modes *mode, u8 channel,
+ u8 bw);
+size_t wpas_supp_op_class_ie(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid,
+ int freq, u8 *pos, size_t len);
/**
* wpa_supplicant_ctrl_iface_ctrl_rsp_handle - Handle a control response
@@ -1238,6 +1445,9 @@ void wnm_bss_keep_alive_deinit(struct wpa_supplicant *wpa_s);
int wpa_supplicant_fast_associate(struct wpa_supplicant *wpa_s);
struct wpa_bss * wpa_supplicant_pick_network(struct wpa_supplicant *wpa_s,
struct wpa_ssid **selected_ssid);
+int wpas_temp_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
+void wpa_supplicant_update_channel_list(struct wpa_supplicant *wpa_s,
+ struct channel_list_changed *info);
/* eap_register.c */
int eap_register_methods(void);
@@ -1290,12 +1500,22 @@ struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
u16 num_modes, enum hostapd_hw_mode mode);
void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
- unsigned int sec);
-int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s, const u8 *bssid);
+ unsigned int sec, int rssi_threshold);
+int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
+ struct wpa_bss *bss);
+void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s);
struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
int i, struct wpa_bss *bss,
struct wpa_ssid *group,
- int only_first_ssid);
+ int only_first_ssid, int debug_print);
+
+int wpas_ctrl_iface_get_pref_freq_list_override(struct wpa_supplicant *wpa_s,
+ enum wpa_driver_if_type if_type,
+ unsigned int *num,
+ unsigned int *freq_list);
+
+int wpa_is_fils_supported(struct wpa_supplicant *wpa_s);
+int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s);
#endif /* WPA_SUPPLICANT_I_H */
diff --git a/freebsd/contrib/wpa/wpa_supplicant/wpas_glue.c b/freebsd/contrib/wpa/wpa_supplicant/wpas_glue.c
index 158cbb07..3dc6a216 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/wpas_glue.c
+++ b/freebsd/contrib/wpa/wpa_supplicant/wpas_glue.c
@@ -12,6 +12,7 @@
#include "common.h"
#include "eapol_supp/eapol_supp_sm.h"
+#include "eap_peer/eap.h"
#include "rsn_supp/wpa.h"
#include "eloop.h"
#include "config.h"
@@ -147,6 +148,8 @@ static int wpa_supplicant_eapol_send(void *ctx, int type, const u8 *buf,
* extra copy here */
if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
+ wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
+ wpa_s->key_mgmt == WPA_KEY_MGMT_DPP ||
wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
/* Current SSID is not using IEEE 802.1X/EAP, so drop possible
* EAPOL frames (mainly, EAPOL-Start) from EAPOL state
@@ -295,7 +298,7 @@ static void wpa_supplicant_eapol_cb(struct eapol_sm *eapol,
}
if (result != EAPOL_SUPP_RESULT_SUCCESS ||
- !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
+ !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X))
return;
if (!wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt))
@@ -501,6 +504,16 @@ static int wpa_supplicant_set_key(void *_wpa_s, enum wpa_alg alg,
wpa_s->last_gtk_len = key_len;
}
#endif /* CONFIG_TESTING_GET_GTK */
+#ifdef CONFIG_TESTING_OPTIONS
+ if (addr && !is_broadcast_ether_addr(addr)) {
+ wpa_s->last_tk_alg = alg;
+ os_memcpy(wpa_s->last_tk_addr, addr, ETH_ALEN);
+ wpa_s->last_tk_key_idx = key_idx;
+ if (key)
+ os_memcpy(wpa_s->last_tk, key, key_len);
+ wpa_s->last_tk_len = key_len;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
return wpa_drv_set_key(wpa_s, alg, addr, key_idx, set_tx, seq, seq_len,
key, key_len);
}
@@ -515,17 +528,74 @@ static int wpa_supplicant_mlme_setprotection(void *wpa_s, const u8 *addr,
}
-static int wpa_supplicant_add_pmkid(void *wpa_s,
- const u8 *bssid, const u8 *pmkid)
+static struct wpa_ssid * wpas_get_network_ctx(struct wpa_supplicant *wpa_s,
+ void *network_ctx)
{
- return wpa_drv_add_pmkid(wpa_s, bssid, pmkid);
+ struct wpa_ssid *ssid;
+
+ for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
+ if (network_ctx == ssid)
+ return ssid;
+ }
+
+ return NULL;
}
-static int wpa_supplicant_remove_pmkid(void *wpa_s,
- const u8 *bssid, const u8 *pmkid)
+static int wpa_supplicant_add_pmkid(void *_wpa_s, void *network_ctx,
+ const u8 *bssid, const u8 *pmkid,
+ const u8 *fils_cache_id,
+ const u8 *pmk, size_t pmk_len)
{
- return wpa_drv_remove_pmkid(wpa_s, bssid, pmkid);
+ struct wpa_supplicant *wpa_s = _wpa_s;
+ struct wpa_ssid *ssid;
+ struct wpa_pmkid_params params;
+
+ os_memset(&params, 0, sizeof(params));
+ ssid = wpas_get_network_ctx(wpa_s, network_ctx);
+ if (ssid)
+ wpa_msg(wpa_s, MSG_INFO, PMKSA_CACHE_ADDED MACSTR " %d",
+ MAC2STR(bssid), ssid->id);
+ if (ssid && fils_cache_id) {
+ params.ssid = ssid->ssid;
+ params.ssid_len = ssid->ssid_len;
+ params.fils_cache_id = fils_cache_id;
+ } else {
+ params.bssid = bssid;
+ }
+
+ params.pmkid = pmkid;
+ params.pmk = pmk;
+ params.pmk_len = pmk_len;
+
+ return wpa_drv_add_pmkid(wpa_s, &params);
+}
+
+
+static int wpa_supplicant_remove_pmkid(void *_wpa_s, void *network_ctx,
+ const u8 *bssid, const u8 *pmkid,
+ const u8 *fils_cache_id)
+{
+ struct wpa_supplicant *wpa_s = _wpa_s;
+ struct wpa_ssid *ssid;
+ struct wpa_pmkid_params params;
+
+ os_memset(&params, 0, sizeof(params));
+ ssid = wpas_get_network_ctx(wpa_s, network_ctx);
+ if (ssid)
+ wpa_msg(wpa_s, MSG_INFO, PMKSA_CACHE_REMOVED MACSTR " %d",
+ MAC2STR(bssid), ssid->id);
+ if (ssid && fils_cache_id) {
+ params.ssid = ssid->ssid;
+ params.ssid_len = ssid->ssid_len;
+ params.fils_cache_id = fils_cache_id;
+ } else {
+ params.bssid = bssid;
+ }
+
+ params.pmkid = pmkid;
+
+ return wpa_drv_remove_pmkid(wpa_s, &params);
}
@@ -867,12 +937,13 @@ static void wpa_supplicant_eap_param_needed(void *ctx,
#ifdef CONFIG_EAP_PROXY
+
static void wpa_supplicant_eap_proxy_cb(void *ctx)
{
struct wpa_supplicant *wpa_s = ctx;
size_t len;
- wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol,
+ wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
wpa_s->imsi, &len);
if (wpa_s->mnc_len > 0) {
wpa_s->imsi[len] = '\0';
@@ -882,6 +953,52 @@ static void wpa_supplicant_eap_proxy_cb(void *ctx)
wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
}
}
+
+
+static void wpa_sm_sim_state_error_handler(struct wpa_supplicant *wpa_s)
+{
+ int i;
+ struct wpa_ssid *ssid;
+ const struct eap_method_type *eap_methods;
+
+ if (!wpa_s->conf)
+ return;
+
+ for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
+ eap_methods = ssid->eap.eap_methods;
+ if (!eap_methods)
+ continue;
+
+ for (i = 0; eap_methods[i].method != EAP_TYPE_NONE; i++) {
+ if (eap_methods[i].vendor == EAP_VENDOR_IETF &&
+ (eap_methods[i].method == EAP_TYPE_SIM ||
+ eap_methods[i].method == EAP_TYPE_AKA ||
+ eap_methods[i].method == EAP_TYPE_AKA_PRIME)) {
+ wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
+ break;
+ }
+ }
+ }
+}
+
+
+static void
+wpa_supplicant_eap_proxy_notify_sim_status(void *ctx,
+ enum eap_proxy_sim_state sim_state)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+
+ wpa_printf(MSG_DEBUG, "eap_proxy: SIM card status %u", sim_state);
+ switch (sim_state) {
+ case SIM_STATE_ERROR:
+ wpa_sm_sim_state_error_handler(wpa_s);
+ break;
+ default:
+ wpa_printf(MSG_DEBUG, "eap_proxy: SIM card status unknown");
+ break;
+ }
+}
+
#endif /* CONFIG_EAP_PROXY */
@@ -923,6 +1040,14 @@ static void wpa_supplicant_status_cb(void *ctx, const char *status,
}
+static void wpa_supplicant_eap_error_cb(void *ctx, int error_code)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+
+ wpas_notify_eap_error(wpa_s, error_code);
+}
+
+
static void wpa_supplicant_set_anon_id(void *ctx, const u8 *id, size_t len)
{
struct wpa_supplicant *wpa_s = ctx;
@@ -992,12 +1117,15 @@ int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s)
ctx->eap_param_needed = wpa_supplicant_eap_param_needed;
#ifdef CONFIG_EAP_PROXY
ctx->eap_proxy_cb = wpa_supplicant_eap_proxy_cb;
+ ctx->eap_proxy_notify_sim_status =
+ wpa_supplicant_eap_proxy_notify_sim_status;
#endif /* CONFIG_EAP_PROXY */
ctx->port_cb = wpa_supplicant_port_cb;
ctx->cb = wpa_supplicant_eapol_cb;
ctx->cert_cb = wpa_supplicant_cert_cb;
ctx->cert_in_cb = wpa_s->conf->cert_in_cb;
ctx->status_cb = wpa_supplicant_status_cb;
+ ctx->eap_error_cb = wpa_supplicant_eap_error_cb;
ctx->set_anon_id = wpa_supplicant_set_anon_id;
ctx->cb_ctx = wpa_s;
wpa_s->eapol = eapol_sm_init(ctx);
@@ -1014,6 +1142,7 @@ int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s)
#ifndef CONFIG_NO_WPA
+
static void wpa_supplicant_set_rekey_offload(void *ctx,
const u8 *kek, size_t kek_len,
const u8 *kck, size_t kck_len,
@@ -1037,6 +1166,34 @@ static int wpa_supplicant_key_mgmt_set_pmk(void *ctx, const u8 *pmk,
else
return 0;
}
+
+
+static void wpa_supplicant_fils_hlp_rx(void *ctx, const u8 *dst, const u8 *src,
+ const u8 *pkt, size_t pkt_len)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+ char *hex;
+ size_t hexlen;
+
+ hexlen = pkt_len * 2 + 1;
+ hex = os_malloc(hexlen);
+ if (!hex)
+ return;
+ wpa_snprintf_hex(hex, hexlen, pkt, pkt_len);
+ wpa_msg(wpa_s, MSG_INFO, FILS_HLP_RX "dst=" MACSTR " src=" MACSTR
+ " frame=%s", MAC2STR(dst), MAC2STR(src), hex);
+ os_free(hex);
+}
+
+
+static int wpa_supplicant_channel_info(void *_wpa_s,
+ struct wpa_channel_info *ci)
+{
+ struct wpa_supplicant *wpa_s = _wpa_s;
+
+ return wpa_drv_channel_info(wpa_s, ci);
+}
+
#endif /* CONFIG_NO_WPA */
@@ -1086,6 +1243,8 @@ int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s)
#endif /* CONFIG_TDLS */
ctx->set_rekey_offload = wpa_supplicant_set_rekey_offload;
ctx->key_mgmt_set_pmk = wpa_supplicant_key_mgmt_set_pmk;
+ ctx->fils_hlp_rx = wpa_supplicant_fils_hlp_rx;
+ ctx->channel_info = wpa_supplicant_channel_info;
wpa_s->wpa = wpa_sm_init(ctx);
if (wpa_s->wpa == NULL) {
@@ -1107,7 +1266,6 @@ void wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s,
if (ssid) {
os_memset(&conf, 0, sizeof(conf));
conf.network_ctx = ssid;
- conf.peerkey_enabled = ssid->peerkey;
conf.allowed_pairwise_cipher = ssid->pairwise_cipher;
#ifdef IEEE8021X_EAPOL
conf.proactive_key_caching = ssid->proactive_key_caching < 0 ?
@@ -1135,6 +1293,11 @@ void wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s,
}
#endif /* CONFIG_P2P */
conf.wpa_rsc_relaxation = wpa_s->conf->wpa_rsc_relaxation;
+#ifdef CONFIG_FILS
+ if (wpa_key_mgmt_fils(wpa_s->key_mgmt))
+ conf.fils_cache_id =
+ wpa_bss_get_fils_cache_id(wpa_s->current_bss);
+#endif /* CONFIG_FILS */
}
wpa_sm_set_config(wpa_s->wpa, ssid ? &conf : NULL);
}
diff --git a/freebsd/contrib/wpa/wpa_supplicant/wpas_kay.h b/freebsd/contrib/wpa/wpa_supplicant/wpas_kay.h
index b7236d07..81f8e0ce 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/wpas_kay.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/wpas_kay.h
@@ -17,6 +17,9 @@ void * ieee802_1x_notify_create_actor(struct wpa_supplicant *wpa_s,
const u8 *peer_addr);
void ieee802_1x_dealloc_kay_sm(struct wpa_supplicant *wpa_s);
+void * ieee802_1x_create_preshared_mka(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid);
+
#else /* CONFIG_MACSEC */
static inline int ieee802_1x_alloc_kay_sm(struct wpa_supplicant *wpa_s,
@@ -36,6 +39,13 @@ static inline void ieee802_1x_dealloc_kay_sm(struct wpa_supplicant *wpa_s)
{
}
+static inline void *
+ieee802_1x_create_preshared_mka(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid)
+{
+ return 0;
+}
+
#endif /* CONFIG_MACSEC */
#endif /* WPAS_KAY_H */
diff --git a/freebsd/contrib/wpa/wpa_supplicant/wps_supplicant.c b/freebsd/contrib/wpa/wpa_supplicant/wps_supplicant.c
index 39440b36..6e33def5 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/wps_supplicant.c
+++ b/freebsd/contrib/wpa/wpa_supplicant/wps_supplicant.c
@@ -205,6 +205,9 @@ static void wpas_wps_security_workaround(struct wpa_supplicant *wpa_s,
if (ssid->ssid == NULL)
return;
bss = wpa_bss_get(wpa_s, cred->mac_addr, ssid->ssid, ssid->ssid_len);
+ if (!bss)
+ bss = wpa_bss_get(wpa_s, wpa_s->bssid,
+ ssid->ssid, ssid->ssid_len);
if (bss == NULL) {
wpa_printf(MSG_DEBUG, "WPS: The AP was not found from BSS "
"table - use credential as-is");
@@ -492,6 +495,16 @@ static int wpa_supplicant_wps_cred(void *ctx,
ssid->pairwise_cipher |= WPA_CIPHER_GCMP;
ssid->group_cipher |= WPA_CIPHER_GCMP;
}
+ if (wpa_s->drv_capa_known &&
+ (wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_GCMP_256)) {
+ ssid->pairwise_cipher |= WPA_CIPHER_GCMP_256;
+ ssid->group_cipher |= WPA_CIPHER_GCMP_256;
+ }
+ if (wpa_s->drv_capa_known &&
+ (wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_CCMP_256)) {
+ ssid->pairwise_cipher |= WPA_CIPHER_CCMP_256;
+ ssid->group_cipher |= WPA_CIPHER_CCMP_256;
+ }
break;
}
@@ -519,11 +532,18 @@ static int wpa_supplicant_wps_cred(void *ctx,
case WPS_AUTH_WPA2PSK:
ssid->auth_alg = WPA_AUTH_ALG_OPEN;
ssid->key_mgmt = WPA_KEY_MGMT_PSK;
+ if (wpa_s->conf->wps_cred_add_sae &&
+ cred->key_len != 2 * PMK_LEN) {
+ ssid->key_mgmt |= WPA_KEY_MGMT_SAE;
+#ifdef CONFIG_IEEE80211W
+ ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
+#endif /* CONFIG_IEEE80211W */
+ }
ssid->proto = WPA_PROTO_RSN;
break;
}
- if (ssid->key_mgmt == WPA_KEY_MGMT_PSK) {
+ if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
if (cred->key_len == 2 * PMK_LEN) {
if (hexstr2bin((const char *) cred->key, ssid->psk,
PMK_LEN)) {
@@ -1029,10 +1049,9 @@ static struct wpa_ssid * wpas_wps_add_network(struct wpa_supplicant *wpa_s,
continue;
os_free(ssid->ssid);
- ssid->ssid = os_malloc(bss->ssid_len);
+ ssid->ssid = os_memdup(bss->ssid, bss->ssid_len);
if (ssid->ssid == NULL)
break;
- os_memcpy(ssid->ssid, bss->ssid, bss->ssid_len);
ssid->ssid_len = bss->ssid_len;
wpa_hexdump_ascii(MSG_DEBUG, "WPS: Picked SSID from "
"scan results",
@@ -1127,9 +1146,10 @@ static void wpas_wps_reassoc(struct wpa_supplicant *wpa_s,
int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid,
- int p2p_group)
+ int p2p_group, int multi_ap_backhaul_sta)
{
struct wpa_ssid *ssid;
+ char phase1[32];
#ifdef CONFIG_AP
if (wpa_s->ap_iface) {
@@ -1167,10 +1187,15 @@ int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid,
}
}
#endif /* CONFIG_P2P */
- if (wpa_config_set(ssid, "phase1", "\"pbc=1\"", 0) < 0)
+ os_snprintf(phase1, sizeof(phase1), "pbc=1%s",
+ multi_ap_backhaul_sta ? " multi_ap=1" : "");
+ if (wpa_config_set_quoted(ssid, "phase1", phase1) < 0)
return -1;
if (wpa_s->wps_fragment_size)
ssid->eap.fragment_size = wpa_s->wps_fragment_size;
+ if (multi_ap_backhaul_sta)
+ ssid->multi_ap_backhaul_sta = 1;
+ wpa_supplicant_wps_event(wpa_s, WPS_EV_PBC_ACTIVE, NULL);
eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout,
wpa_s, NULL);
wpas_wps_reassoc(wpa_s, ssid, bssid, 0);
@@ -1483,6 +1508,9 @@ static void wpas_wps_set_uuid(struct wpa_supplicant *wpa_s,
wpa_s->global->ifaces->wps->uuid,
WPS_UUID_LEN);
src = "from the first interface";
+ } else if (wpa_s->conf->auto_uuid == 1) {
+ uuid_random(wps->uuid);
+ src = "based on random data";
} else {
uuid_gen_mac_addr(wpa_s->own_addr, wps->uuid);
src = "based on MAC address";
diff --git a/freebsd/contrib/wpa/wpa_supplicant/wps_supplicant.h b/freebsd/contrib/wpa/wpa_supplicant/wps_supplicant.h
index c8fe47e3..0fbc8517 100644
--- a/freebsd/contrib/wpa/wpa_supplicant/wps_supplicant.h
+++ b/freebsd/contrib/wpa/wpa_supplicant/wps_supplicant.h
@@ -30,7 +30,7 @@ void wpas_wps_deinit(struct wpa_supplicant *wpa_s);
int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s);
enum wps_request_type wpas_wps_get_req_type(struct wpa_ssid *ssid);
int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid,
- int p2p_group);
+ int p2p_group, int multi_ap_backhaul_sta);
int wpas_wps_start_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
const char *pin, int p2p_group, u16 dev_pw_id);
void wpas_wps_pbc_overlap(struct wpa_supplicant *wpa_s);
diff --git a/freebsd/crypto/openssl/apps/asn1pars.c b/freebsd/crypto/openssl/apps/asn1pars.c
index ec75690e..b9e29e6b 100644
--- a/freebsd/crypto/openssl/apps/asn1pars.c
+++ b/freebsd/crypto/openssl/apps/asn1pars.c
@@ -6,7 +6,7 @@
#endif /* __rtems__ */
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -177,17 +177,17 @@ int asn1parse_main(int argc, char **argv)
if (derfile && (derout = bio_open_default(derfile, 'w', FORMAT_ASN1)) == NULL)
goto end;
+ if ((buf = BUF_MEM_new()) == NULL)
+ goto end;
if (strictpem) {
- if (PEM_read_bio(in, &name, &header, &str, &num) !=
- 1) {
+ if (PEM_read_bio(in, &name, &header, &str, &num) != 1) {
BIO_printf(bio_err, "Error reading PEM file\n");
ERR_print_errors(bio_err);
goto end;
}
+ buf->data = (char *)str;
+ buf->length = buf->max = num;
} else {
-
- if ((buf = BUF_MEM_new()) == NULL)
- goto end;
if (!BUF_MEM_grow(buf, BUFSIZ * 8))
goto end; /* Pre-allocate :-) */
@@ -310,8 +310,6 @@ int asn1parse_main(int argc, char **argv)
BUF_MEM_free(buf);
OPENSSL_free(name);
OPENSSL_free(header);
- if (strictpem)
- OPENSSL_free(str);
ASN1_TYPE_free(at);
sk_OPENSSL_STRING_free(osk);
return ret;
diff --git a/freebsd/crypto/openssl/apps/cms.c b/freebsd/crypto/openssl/apps/cms.c
index b1340a34..43c132c2 100644
--- a/freebsd/crypto/openssl/apps/cms.c
+++ b/freebsd/crypto/openssl/apps/cms.c
@@ -6,7 +6,7 @@
#endif /* __rtems__ */
/*
- * Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2008-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -643,6 +643,7 @@ int cms_main(int argc, char **argv)
goto opthelp;
}
} else if (!operation) {
+ BIO_printf(bio_err, "No operation option (-encrypt|-decrypt|-sign|-verify|...) specified.\n");
goto opthelp;
}
diff --git a/freebsd/crypto/openssl/apps/enc.c b/freebsd/crypto/openssl/apps/enc.c
index ddbea12e..35200315 100644
--- a/freebsd/crypto/openssl/apps/enc.c
+++ b/freebsd/crypto/openssl/apps/enc.c
@@ -6,7 +6,7 @@
#endif /* __rtems__ */
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -512,7 +512,7 @@ int enc_main(int argc, char **argv)
if (hiv != NULL) {
int siz = EVP_CIPHER_iv_length(cipher);
if (siz == 0) {
- BIO_printf(bio_err, "warning: iv not use by this cipher\n");
+ BIO_printf(bio_err, "warning: iv not used by this cipher\n");
} else if (!set_hex(hiv, iv, siz)) {
BIO_printf(bio_err, "invalid hex iv value\n");
goto end;
diff --git a/freebsd/crypto/openssl/apps/ocsp.c b/freebsd/crypto/openssl/apps/ocsp.c
index 056fdc02..2aaf3b9f 100644
--- a/freebsd/crypto/openssl/apps/ocsp.c
+++ b/freebsd/crypto/openssl/apps/ocsp.c
@@ -648,8 +648,10 @@ redo_accept:
goto end;
}
- if (req != NULL && add_nonce)
- OCSP_request_add1_nonce(req, NULL, -1);
+ if (req != NULL && add_nonce) {
+ if (!OCSP_request_add1_nonce(req, NULL, -1))
+ goto end;
+ }
if (signfile != NULL) {
if (keyfile == NULL)
@@ -1252,7 +1254,10 @@ static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req
goto end;
}
}
- OCSP_basic_sign_ctx(bs, rcert, mctx, rother, flags);
+ if (!OCSP_basic_sign_ctx(bs, rcert, mctx, rother, flags)) {
+ *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR, bs);
+ goto end;
+ }
if (badsig) {
const ASN1_OCTET_STRING *sig = OCSP_resp_get0_signature(bs);
diff --git a/freebsd/crypto/openssl/apps/s_cb.c b/freebsd/crypto/openssl/apps/s_cb.c
index f8524620..3df95478 100644
--- a/freebsd/crypto/openssl/apps/s_cb.c
+++ b/freebsd/crypto/openssl/apps/s_cb.c
@@ -690,6 +690,53 @@ static STRINT_PAIR tlsext_types[] = {
{NULL}
};
+/* from rfc8446 4.2.3. + gost (https://tools.ietf.org/id/draft-smyshlyaev-tls12-gost-suites-04.html) */
+static STRINT_PAIR signature_tls13_scheme_list[] = {
+ {"rsa_pkcs1_sha1", 0x0201 /* TLSEXT_SIGALG_rsa_pkcs1_sha1 */},
+ {"ecdsa_sha1", 0x0203 /* TLSEXT_SIGALG_ecdsa_sha1 */},
+/* {"rsa_pkcs1_sha224", 0x0301 TLSEXT_SIGALG_rsa_pkcs1_sha224}, not in rfc8446 */
+/* {"ecdsa_sha224", 0x0303 TLSEXT_SIGALG_ecdsa_sha224} not in rfc8446 */
+ {"rsa_pkcs1_sha256", 0x0401 /* TLSEXT_SIGALG_rsa_pkcs1_sha256 */},
+ {"ecdsa_secp256r1_sha256", 0x0403 /* TLSEXT_SIGALG_ecdsa_secp256r1_sha256 */},
+ {"rsa_pkcs1_sha384", 0x0501 /* TLSEXT_SIGALG_rsa_pkcs1_sha384 */},
+ {"ecdsa_secp384r1_sha384", 0x0503 /* TLSEXT_SIGALG_ecdsa_secp384r1_sha384 */},
+ {"rsa_pkcs1_sha512", 0x0601 /* TLSEXT_SIGALG_rsa_pkcs1_sha512 */},
+ {"ecdsa_secp521r1_sha512", 0x0603 /* TLSEXT_SIGALG_ecdsa_secp521r1_sha512 */},
+ {"rsa_pss_rsae_sha256", 0x0804 /* TLSEXT_SIGALG_rsa_pss_rsae_sha256 */},
+ {"rsa_pss_rsae_sha384", 0x0805 /* TLSEXT_SIGALG_rsa_pss_rsae_sha384 */},
+ {"rsa_pss_rsae_sha512", 0x0806 /* TLSEXT_SIGALG_rsa_pss_rsae_sha512 */},
+ {"ed25519", 0x0807 /* TLSEXT_SIGALG_ed25519 */},
+ {"ed448", 0x0808 /* TLSEXT_SIGALG_ed448 */},
+ {"rsa_pss_pss_sha256", 0x0809 /* TLSEXT_SIGALG_rsa_pss_pss_sha256 */},
+ {"rsa_pss_pss_sha384", 0x080a /* TLSEXT_SIGALG_rsa_pss_pss_sha384 */},
+ {"rsa_pss_pss_sha512", 0x080b /* TLSEXT_SIGALG_rsa_pss_pss_sha512 */},
+ {"gostr34102001", 0xeded /* TLSEXT_SIGALG_gostr34102001_gostr3411 */},
+ {"gostr34102012_256", 0xeeee /* TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256 */},
+ {"gostr34102012_512", 0xefef /* TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512 */},
+ {NULL}
+};
+
+/* from rfc5246 7.4.1.4.1. */
+static STRINT_PAIR signature_tls12_alg_list[] = {
+ {"anonymous", TLSEXT_signature_anonymous /* 0 */},
+ {"RSA", TLSEXT_signature_rsa /* 1 */},
+ {"DSA", TLSEXT_signature_dsa /* 2 */},
+ {"ECDSA", TLSEXT_signature_ecdsa /* 3 */},
+ {NULL}
+};
+
+/* from rfc5246 7.4.1.4.1. */
+static STRINT_PAIR signature_tls12_hash_list[] = {
+ {"none", TLSEXT_hash_none /* 0 */},
+ {"MD5", TLSEXT_hash_md5 /* 1 */},
+ {"SHA1", TLSEXT_hash_sha1 /* 2 */},
+ {"SHA224", TLSEXT_hash_sha224 /* 3 */},
+ {"SHA256", TLSEXT_hash_sha256 /* 4 */},
+ {"SHA384", TLSEXT_hash_sha384 /* 5 */},
+ {"SHA512", TLSEXT_hash_sha512 /* 6 */},
+ {NULL}
+};
+
void tlsext_cb(SSL *s, int client_server, int type,
const unsigned char *data, int len, void *arg)
{
@@ -1294,9 +1341,9 @@ static STRINT_PAIR callback_types[] = {
{"Supported Curve", SSL_SECOP_CURVE_SUPPORTED},
{"Shared Curve", SSL_SECOP_CURVE_SHARED},
{"Check Curve", SSL_SECOP_CURVE_CHECK},
- {"Supported Signature Algorithm digest", SSL_SECOP_SIGALG_SUPPORTED},
- {"Shared Signature Algorithm digest", SSL_SECOP_SIGALG_SHARED},
- {"Check Signature Algorithm digest", SSL_SECOP_SIGALG_CHECK},
+ {"Supported Signature Algorithm", SSL_SECOP_SIGALG_SUPPORTED},
+ {"Shared Signature Algorithm", SSL_SECOP_SIGALG_SHARED},
+ {"Check Signature Algorithm", SSL_SECOP_SIGALG_CHECK},
{"Signature Algorithm mask", SSL_SECOP_SIGALG_MASK},
{"Certificate chain EE key", SSL_SECOP_EE_KEY},
{"Certificate chain CA key", SSL_SECOP_CA_KEY},
@@ -1316,29 +1363,37 @@ static int security_callback_debug(const SSL *s, const SSL_CTX *ctx,
security_debug_ex *sdb = ex;
int rv, show_bits = 1, cert_md = 0;
const char *nm;
+ int show_nm;
rv = sdb->old_cb(s, ctx, op, bits, nid, other, ex);
if (rv == 1 && sdb->verbose < 2)
return 1;
BIO_puts(sdb->out, "Security callback: ");
nm = lookup(op, callback_types, NULL);
+ show_nm = nm != NULL;
switch (op) {
case SSL_SECOP_TICKET:
case SSL_SECOP_COMPRESSION:
show_bits = 0;
- nm = NULL;
+ show_nm = 0;
break;
case SSL_SECOP_VERSION:
BIO_printf(sdb->out, "Version=%s", lookup(nid, ssl_versions, "???"));
show_bits = 0;
- nm = NULL;
+ show_nm = 0;
break;
case SSL_SECOP_CA_MD:
case SSL_SECOP_PEER_CA_MD:
cert_md = 1;
break;
+ case SSL_SECOP_SIGALG_SUPPORTED:
+ case SSL_SECOP_SIGALG_SHARED:
+ case SSL_SECOP_SIGALG_CHECK:
+ case SSL_SECOP_SIGALG_MASK:
+ show_nm = 0;
+ break;
}
- if (nm != NULL)
+ if (show_nm)
BIO_printf(sdb->out, "%s=", nm);
switch (op & SSL_SECOP_OTHER_TYPE) {
@@ -1385,27 +1440,28 @@ static int security_callback_debug(const SSL *s, const SSL_CTX *ctx,
{
const unsigned char *salg = other;
const char *sname = NULL;
- switch (salg[1]) {
- case TLSEXT_signature_anonymous:
- sname = "anonymous";
- break;
- case TLSEXT_signature_rsa:
- sname = "RSA";
- break;
- case TLSEXT_signature_dsa:
- sname = "DSA";
- break;
- case TLSEXT_signature_ecdsa:
- sname = "ECDSA";
- break;
- }
+ int raw_sig_code = (salg[0] << 8) + salg[1]; /* always big endian (msb, lsb) */
+ /* raw_sig_code: signature_scheme from tls1.3, or signature_and_hash from tls1.2 */
- BIO_puts(sdb->out, OBJ_nid2sn(nid));
- if (sname)
- BIO_printf(sdb->out, ", algorithm=%s", sname);
+ if (nm != NULL)
+ BIO_printf(sdb->out, "%s", nm);
else
- BIO_printf(sdb->out, ", algid=%d", salg[1]);
- break;
+ BIO_printf(sdb->out, "s_cb.c:security_callback_debug op=0x%x", op);
+
+ sname = lookup(raw_sig_code, signature_tls13_scheme_list, NULL);
+ if (sname != NULL) {
+ BIO_printf(sdb->out, " scheme=%s", sname);
+ } else {
+ int alg_code = salg[1];
+ int hash_code = salg[0];
+ const char *alg_str = lookup(alg_code, signature_tls12_alg_list, NULL);
+ const char *hash_str = lookup(hash_code, signature_tls12_hash_list, NULL);
+
+ if (alg_str != NULL && hash_str != NULL)
+ BIO_printf(sdb->out, " digest=%s, algorithm=%s", hash_str, alg_str);
+ else
+ BIO_printf(sdb->out, " scheme=unknown(0x%04x)", raw_sig_code);
+ }
}
}
diff --git a/freebsd/crypto/openssl/apps/s_client.c b/freebsd/crypto/openssl/apps/s_client.c
index 086220b4..4c052ef5 100644
--- a/freebsd/crypto/openssl/apps/s_client.c
+++ b/freebsd/crypto/openssl/apps/s_client.c
@@ -2275,7 +2275,7 @@ int s_client_main(int argc, char **argv)
do {
mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
}
- while (mbuf_len > 3 && mbuf[3] == '-');
+ while (mbuf_len > 3 && (!isdigit(mbuf[0]) || !isdigit(mbuf[1]) || !isdigit(mbuf[2]) || mbuf[3] != ' '));
(void)BIO_flush(fbio);
BIO_pop(fbio);
BIO_free(fbio);
diff --git a/freebsd/crypto/openssl/apps/speed.c b/freebsd/crypto/openssl/apps/speed.c
index bf429758..02eb30a6 100644
--- a/freebsd/crypto/openssl/apps/speed.c
+++ b/freebsd/crypto/openssl/apps/speed.c
@@ -499,30 +499,35 @@ static const OPT_PAIR rsa_choices[] = {
static double rsa_results[RSA_NUM][2]; /* 2 ops: sign then verify */
#endif /* OPENSSL_NO_RSA */
-#define R_EC_P160 0
-#define R_EC_P192 1
-#define R_EC_P224 2
-#define R_EC_P256 3
-#define R_EC_P384 4
-#define R_EC_P521 5
-#define R_EC_K163 6
-#define R_EC_K233 7
-#define R_EC_K283 8
-#define R_EC_K409 9
-#define R_EC_K571 10
-#define R_EC_B163 11
-#define R_EC_B233 12
-#define R_EC_B283 13
-#define R_EC_B409 14
-#define R_EC_B571 15
-#define R_EC_BRP256R1 16
-#define R_EC_BRP256T1 17
-#define R_EC_BRP384R1 18
-#define R_EC_BRP384T1 19
-#define R_EC_BRP512R1 20
-#define R_EC_BRP512T1 21
-#define R_EC_X25519 22
-#define R_EC_X448 23
+enum {
+ R_EC_P160,
+ R_EC_P192,
+ R_EC_P224,
+ R_EC_P256,
+ R_EC_P384,
+ R_EC_P521,
+#ifndef OPENSSL_NO_EC2M
+ R_EC_K163,
+ R_EC_K233,
+ R_EC_K283,
+ R_EC_K409,
+ R_EC_K571,
+ R_EC_B163,
+ R_EC_B233,
+ R_EC_B283,
+ R_EC_B409,
+ R_EC_B571,
+#endif
+ R_EC_BRP256R1,
+ R_EC_BRP256T1,
+ R_EC_BRP384R1,
+ R_EC_BRP384T1,
+ R_EC_BRP512R1,
+ R_EC_BRP512T1,
+ R_EC_X25519,
+ R_EC_X448
+};
+
#ifndef OPENSSL_NO_EC
static OPT_PAIR ecdsa_choices[] = {
{"ecdsap160", R_EC_P160},
@@ -531,6 +536,7 @@ static OPT_PAIR ecdsa_choices[] = {
{"ecdsap256", R_EC_P256},
{"ecdsap384", R_EC_P384},
{"ecdsap521", R_EC_P521},
+# ifndef OPENSSL_NO_EC2M
{"ecdsak163", R_EC_K163},
{"ecdsak233", R_EC_K233},
{"ecdsak283", R_EC_K283},
@@ -541,6 +547,7 @@ static OPT_PAIR ecdsa_choices[] = {
{"ecdsab283", R_EC_B283},
{"ecdsab409", R_EC_B409},
{"ecdsab571", R_EC_B571},
+# endif
{"ecdsabrp256r1", R_EC_BRP256R1},
{"ecdsabrp256t1", R_EC_BRP256T1},
{"ecdsabrp384r1", R_EC_BRP384R1},
@@ -559,6 +566,7 @@ static const OPT_PAIR ecdh_choices[] = {
{"ecdhp256", R_EC_P256},
{"ecdhp384", R_EC_P384},
{"ecdhp521", R_EC_P521},
+# ifndef OPENSSL_NO_EC2M
{"ecdhk163", R_EC_K163},
{"ecdhk233", R_EC_K233},
{"ecdhk283", R_EC_K283},
@@ -569,6 +577,7 @@ static const OPT_PAIR ecdh_choices[] = {
{"ecdhb283", R_EC_B283},
{"ecdhb409", R_EC_B409},
{"ecdhb571", R_EC_B571},
+# endif
{"ecdhbrp256r1", R_EC_BRP256R1},
{"ecdhbrp256t1", R_EC_BRP256T1},
{"ecdhbrp384r1", R_EC_BRP384R1},
@@ -1520,6 +1529,7 @@ int speed_main(int argc, char **argv)
{"nistp256", NID_X9_62_prime256v1, 256},
{"nistp384", NID_secp384r1, 384},
{"nistp521", NID_secp521r1, 521},
+# ifndef OPENSSL_NO_EC2M
/* Binary Curves */
{"nistk163", NID_sect163k1, 163},
{"nistk233", NID_sect233k1, 233},
@@ -1531,6 +1541,7 @@ int speed_main(int argc, char **argv)
{"nistb283", NID_sect283r1, 283},
{"nistb409", NID_sect409r1, 409},
{"nistb571", NID_sect571r1, 571},
+# endif
{"brainpoolP256r1", NID_brainpoolP256r1, 256},
{"brainpoolP256t1", NID_brainpoolP256t1, 256},
{"brainpoolP384r1", NID_brainpoolP384r1, 384},
@@ -2050,6 +2061,7 @@ int speed_main(int argc, char **argv)
}
}
}
+# ifndef OPENSSL_NO_EC2M
ecdsa_c[R_EC_K163][0] = count / 1000;
ecdsa_c[R_EC_K163][1] = count / 1000 / 2;
for (i = R_EC_K233; i <= R_EC_K571; i++) {
@@ -2078,6 +2090,7 @@ int speed_main(int argc, char **argv)
}
}
}
+# endif
ecdh_c[R_EC_P160][0] = count / 1000;
for (i = R_EC_P192; i <= R_EC_P521; i++) {
@@ -2090,6 +2103,7 @@ int speed_main(int argc, char **argv)
}
}
}
+# ifndef OPENSSL_NO_EC2M
ecdh_c[R_EC_K163][0] = count / 1000;
for (i = R_EC_K233; i <= R_EC_K571; i++) {
ecdh_c[i][0] = ecdh_c[i - 1][0] / 2;
@@ -2112,6 +2126,7 @@ int speed_main(int argc, char **argv)
}
}
}
+# endif
/* repeated code good to factorize */
ecdh_c[R_EC_BRP256R1][0] = count / 1000;
for (i = R_EC_BRP384R1; i <= R_EC_BRP512R1; i += 2) {
@@ -2633,16 +2648,28 @@ int speed_main(int argc, char **argv)
for (k = 0; k < loopargs_len; k++) {
loopargs[k].ctx = EVP_CIPHER_CTX_new();
- EVP_CipherInit_ex(loopargs[k].ctx, evp_cipher, NULL, NULL,
- iv, decrypt ? 0 : 1);
+ if (loopargs[k].ctx == NULL) {
+ BIO_printf(bio_err, "\nEVP_CIPHER_CTX_new failure\n");
+ exit(1);
+ }
+ if (!EVP_CipherInit_ex(loopargs[k].ctx, evp_cipher, NULL,
+ NULL, iv, decrypt ? 0 : 1)) {
+ BIO_printf(bio_err, "\nEVP_CipherInit_ex failure\n");
+ ERR_print_errors(bio_err);
+ exit(1);
+ }
EVP_CIPHER_CTX_set_padding(loopargs[k].ctx, 0);
keylen = EVP_CIPHER_CTX_key_length(loopargs[k].ctx);
loopargs[k].key = app_malloc(keylen, "evp_cipher key");
EVP_CIPHER_CTX_rand_key(loopargs[k].ctx, loopargs[k].key);
- EVP_CipherInit_ex(loopargs[k].ctx, NULL, NULL,
- loopargs[k].key, NULL, -1);
+ if (!EVP_CipherInit_ex(loopargs[k].ctx, NULL, NULL,
+ loopargs[k].key, NULL, -1)) {
+ BIO_printf(bio_err, "\nEVP_CipherInit_ex failure\n");
+ ERR_print_errors(bio_err);
+ exit(1);
+ }
OPENSSL_clear_free(loopargs[k].key, keylen);
}
diff --git a/freebsd/crypto/openssl/crypto/bio/b_addr.c b/freebsd/crypto/openssl/crypto/bio/b_addr.c
index 0818431f..5a672da6 100644
--- a/freebsd/crypto/openssl/crypto/bio/b_addr.c
+++ b/freebsd/crypto/openssl/crypto/bio/b_addr.c
@@ -685,6 +685,12 @@ int BIO_lookup_ex(const char *host, const char *service, int lookup_type,
hints.ai_family = family;
hints.ai_socktype = socktype;
hints.ai_protocol = protocol;
+#ifdef AI_ADDRCONFIG
+#ifdef AF_UNSPEC
+ if (family == AF_UNSPEC)
+#endif
+ hints.ai_flags |= AI_ADDRCONFIG;
+#endif
if (lookup_type == BIO_LOOKUP_SERVER)
hints.ai_flags |= AI_PASSIVE;
diff --git a/freebsd/crypto/openssl/crypto/bio/bss_mem.c b/freebsd/crypto/openssl/crypto/bio/bss_mem.c
index 0e02d0c0..8f14d790 100644
--- a/freebsd/crypto/openssl/crypto/bio/bss_mem.c
+++ b/freebsd/crypto/openssl/crypto/bio/bss_mem.c
@@ -59,7 +59,12 @@ static const BIO_METHOD secmem_method = {
NULL, /* mem_callback_ctrl */
};
-/* BIO memory stores buffer and read pointer */
+/*
+ * BIO memory stores buffer and read pointer
+ * however the roles are different for read only BIOs.
+ * In that case the readp just stores the original state
+ * to be used for reset.
+ */
typedef struct bio_buf_mem_st {
struct buf_mem_st *buf; /* allocated buffer */
struct buf_mem_st *readp; /* read pointer */
@@ -194,11 +199,14 @@ static int mem_read(BIO *b, char *out, int outl)
BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr;
BUF_MEM *bm = bbm->readp;
+ if (b->flags & BIO_FLAGS_MEM_RDONLY)
+ bm = bbm->buf;
BIO_clear_retry_flags(b);
ret = (outl >= 0 && (size_t)outl > bm->length) ? (int)bm->length : outl;
if ((out != NULL) && (ret > 0)) {
memcpy(out, bm->data, ret);
bm->length -= ret;
+ bm->max -= ret;
bm->data += ret;
} else if (bm->length == 0) {
ret = b->num;
@@ -243,29 +251,36 @@ static long mem_ctrl(BIO *b, int cmd, long num, void *ptr)
BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr;
BUF_MEM *bm;
+ if (b->flags & BIO_FLAGS_MEM_RDONLY)
+ bm = bbm->buf;
+ else
+ bm = bbm->readp;
+
switch (cmd) {
case BIO_CTRL_RESET:
bm = bbm->buf;
if (bm->data != NULL) {
- /* For read only case reset to the start again */
- if ((b->flags & BIO_FLAGS_MEM_RDONLY) || (b->flags & BIO_FLAGS_NONCLEAR_RST)) {
- bm->length = bm->max;
+ if (!(b->flags & BIO_FLAGS_MEM_RDONLY)) {
+ if (b->flags & BIO_FLAGS_NONCLEAR_RST) {
+ bm->length = bm->max;
+ } else {
+ memset(bm->data, 0, bm->max);
+ bm->length = 0;
+ }
+ *bbm->readp = *bbm->buf;
} else {
- memset(bm->data, 0, bm->max);
- bm->length = 0;
+ /* For read only case just reset to the start again */
+ *bbm->buf = *bbm->readp;
}
- *bbm->readp = *bbm->buf;
}
break;
case BIO_CTRL_EOF:
- bm = bbm->readp;
ret = (long)(bm->length == 0);
break;
case BIO_C_SET_BUF_MEM_EOF_RETURN:
b->num = (int)num;
break;
case BIO_CTRL_INFO:
- bm = bbm->readp;
ret = (long)bm->length;
if (ptr != NULL) {
pptr = (char **)ptr;
@@ -280,8 +295,9 @@ static long mem_ctrl(BIO *b, int cmd, long num, void *ptr)
break;
case BIO_C_GET_BUF_MEM_PTR:
if (ptr != NULL) {
- mem_buf_sync(b);
- bm = bbm->readp;
+ if (!(b->flags & BIO_FLAGS_MEM_RDONLY))
+ mem_buf_sync(b);
+ bm = bbm->buf;
pptr = (char **)ptr;
*pptr = (char *)bm;
}
@@ -296,7 +312,6 @@ static long mem_ctrl(BIO *b, int cmd, long num, void *ptr)
ret = 0L;
break;
case BIO_CTRL_PENDING:
- bm = bbm->readp;
ret = (long)bm->length;
break;
case BIO_CTRL_DUP:
@@ -320,6 +335,8 @@ static int mem_gets(BIO *bp, char *buf, int size)
BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)bp->ptr;
BUF_MEM *bm = bbm->readp;
+ if (bp->flags & BIO_FLAGS_MEM_RDONLY)
+ bm = bbm->buf;
BIO_clear_retry_flags(bp);
j = bm->length;
if ((size - 1) < j)
diff --git a/freebsd/crypto/openssl/crypto/blake2/blake2b.c b/freebsd/crypto/openssl/crypto/blake2/blake2b.c
index 461d1318..efbdbeb0 100644
--- a/freebsd/crypto/openssl/crypto/blake2/blake2b.c
+++ b/freebsd/crypto/openssl/crypto/blake2/blake2b.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -25,10 +25,10 @@
static const uint64_t blake2b_IV[8] =
{
- 0x6a09e667f3bcc908U, 0xbb67ae8584caa73bU,
- 0x3c6ef372fe94f82bU, 0xa54ff53a5f1d36f1U,
- 0x510e527fade682d1U, 0x9b05688c2b3e6c1fU,
- 0x1f83d9abfb41bd6bU, 0x5be0cd19137e2179U
+ 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
+ 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
+ 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
+ 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
};
static const uint8_t blake2b_sigma[12][16] =
diff --git a/freebsd/crypto/openssl/crypto/bn/bn_ctx.c b/freebsd/crypto/openssl/crypto/bn/bn_ctx.c
index 5db64ef6..96bcde8a 100644
--- a/freebsd/crypto/openssl/crypto/bn/bn_ctx.c
+++ b/freebsd/crypto/openssl/crypto/bn/bn_ctx.c
@@ -196,6 +196,8 @@ void BN_CTX_start(BN_CTX *ctx)
void BN_CTX_end(BN_CTX *ctx)
{
+ if (ctx == NULL)
+ return;
CTXDBG_ENTRY("BN_CTX_end", ctx);
if (ctx->err_stack)
ctx->err_stack--;
diff --git a/freebsd/crypto/openssl/crypto/bn/bn_lib.c b/freebsd/crypto/openssl/crypto/bn/bn_lib.c
index a37d5441..e900e4ae 100644
--- a/freebsd/crypto/openssl/crypto/bn/bn_lib.c
+++ b/freebsd/crypto/openssl/crypto/bn/bn_lib.c
@@ -340,6 +340,8 @@ void BN_swap(BIGNUM *a, BIGNUM *b)
void BN_clear(BIGNUM *a)
{
+ if (a == NULL)
+ return;
bn_check_top(a);
if (a->d != NULL)
OPENSSL_cleanse(a->d, sizeof(*a->d) * a->dmax);
diff --git a/freebsd/crypto/openssl/crypto/bn/bn_prime.c b/freebsd/crypto/openssl/crypto/bn/bn_prime.c
index 9e924a55..c379eab8 100644
--- a/freebsd/crypto/openssl/crypto/bn/bn_prime.c
+++ b/freebsd/crypto/openssl/crypto/bn/bn_prime.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -137,8 +137,7 @@ int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe,
found = 1;
err:
OPENSSL_free(mods);
- if (ctx != NULL)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(ctx);
bn_check_top(ret);
return found;
diff --git a/freebsd/crypto/openssl/crypto/conf/conf_sap.c b/freebsd/crypto/openssl/crypto/conf/conf_sap.c
index a76b3660..5010574b 100644
--- a/freebsd/crypto/openssl/crypto/conf/conf_sap.c
+++ b/freebsd/crypto/openssl/crypto/conf/conf_sap.c
@@ -37,6 +37,7 @@ void OPENSSL_config(const char *appname)
memset(&settings, 0, sizeof(settings));
if (appname != NULL)
settings.appname = strdup(appname);
+ settings.flags = DEFAULT_CONF_MFLAGS;
OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, &settings);
}
#endif
diff --git a/freebsd/crypto/openssl/crypto/dh/dh_check.c b/freebsd/crypto/openssl/crypto/dh/dh_check.c
index ff5d8f81..0ff2d5f7 100644
--- a/freebsd/crypto/openssl/crypto/dh/dh_check.c
+++ b/freebsd/crypto/openssl/crypto/dh/dh_check.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -14,6 +14,8 @@
#include <openssl/bn.h>
#include "dh_locl.h"
+# define DH_NUMBER_ITERATIONS_FOR_PRIME 64
+
/*-
* Check that p and g are suitable enough
*
@@ -60,10 +62,8 @@ int DH_check_params(const DH *dh, int *ret)
ok = 1;
err:
- if (ctx != NULL) {
- BN_CTX_end(ctx);
- BN_CTX_free(ctx);
- }
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
return ok;
}
@@ -129,7 +129,7 @@ int DH_check(const DH *dh, int *ret)
if (!BN_is_one(t1))
*ret |= DH_NOT_SUITABLE_GENERATOR;
}
- r = BN_is_prime_ex(dh->q, BN_prime_checks, ctx, NULL);
+ r = BN_is_prime_ex(dh->q, DH_NUMBER_ITERATIONS_FOR_PRIME, ctx, NULL);
if (r < 0)
goto err;
if (!r)
@@ -157,7 +157,7 @@ int DH_check(const DH *dh, int *ret)
} else
*ret |= DH_UNABLE_TO_CHECK_GENERATOR;
- r = BN_is_prime_ex(dh->p, BN_prime_checks, ctx, NULL);
+ r = BN_is_prime_ex(dh->p, DH_NUMBER_ITERATIONS_FOR_PRIME, ctx, NULL);
if (r < 0)
goto err;
if (!r)
@@ -165,7 +165,7 @@ int DH_check(const DH *dh, int *ret)
else if (!dh->q) {
if (!BN_rshift1(t1, dh->p))
goto err;
- r = BN_is_prime_ex(t1, BN_prime_checks, ctx, NULL);
+ r = BN_is_prime_ex(t1, DH_NUMBER_ITERATIONS_FOR_PRIME, ctx, NULL);
if (r < 0)
goto err;
if (!r)
@@ -173,10 +173,8 @@ int DH_check(const DH *dh, int *ret)
}
ok = 1;
err:
- if (ctx != NULL) {
- BN_CTX_end(ctx);
- BN_CTX_free(ctx);
- }
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
return ok;
}
@@ -227,9 +225,7 @@ int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret)
ok = 1;
err:
- if (ctx != NULL) {
- BN_CTX_end(ctx);
- BN_CTX_free(ctx);
- }
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
return ok;
}
diff --git a/freebsd/crypto/openssl/crypto/dh/dh_gen.c b/freebsd/crypto/openssl/crypto/dh/dh_gen.c
index 74079d40..74c9cdbb 100644
--- a/freebsd/crypto/openssl/crypto/dh/dh_gen.c
+++ b/freebsd/crypto/openssl/crypto/dh/dh_gen.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -124,9 +124,7 @@ static int dh_builtin_genparams(DH *ret, int prime_len, int generator,
ok = 0;
}
- if (ctx != NULL) {
- BN_CTX_end(ctx);
- BN_CTX_free(ctx);
- }
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
return ok;
}
diff --git a/freebsd/crypto/openssl/crypto/dh/dh_key.c b/freebsd/crypto/openssl/crypto/dh/dh_key.c
index 4cf29bc7..64d6e7da 100644
--- a/freebsd/crypto/openssl/crypto/dh/dh_key.c
+++ b/freebsd/crypto/openssl/crypto/dh/dh_key.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -207,10 +207,8 @@ static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
ret = BN_bn2bin(tmp, key);
err:
- if (ctx != NULL) {
- BN_CTX_end(ctx);
- BN_CTX_free(ctx);
- }
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
return ret;
}
diff --git a/freebsd/crypto/openssl/crypto/dh/dh_pmeth.c b/freebsd/crypto/openssl/crypto/dh/dh_pmeth.c
index b2fa93c4..a182378e 100644
--- a/freebsd/crypto/openssl/crypto/dh/dh_pmeth.c
+++ b/freebsd/crypto/openssl/crypto/dh/dh_pmeth.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -56,7 +56,7 @@ static int pkey_dh_init(EVP_PKEY_CTX *ctx)
DHerr(DH_F_PKEY_DH_INIT, ERR_R_MALLOC_FAILURE);
return 0;
}
- dctx->prime_len = 1024;
+ dctx->prime_len = 2048;
dctx->subprime_len = -1;
dctx->generator = 2;
dctx->kdf_type = EVP_PKEY_DH_KDF_NONE;
diff --git a/freebsd/crypto/openssl/crypto/dsa/dsa_gen.c b/freebsd/crypto/openssl/crypto/dsa/dsa_gen.c
index 84d18b3d..a16a61eb 100644
--- a/freebsd/crypto/openssl/crypto/dsa/dsa_gen.c
+++ b/freebsd/crypto/openssl/crypto/dsa/dsa_gen.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -294,8 +294,7 @@ int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits,
if (seed_out)
memcpy(seed_out, seed, qsize);
}
- if (ctx)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(ctx);
BN_MONT_CTX_free(mont);
return ok;
@@ -609,8 +608,7 @@ int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N,
OPENSSL_free(seed);
if (seed_out != seed_tmp)
OPENSSL_free(seed_tmp);
- if (ctx)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(ctx);
BN_MONT_CTX_free(mont);
EVP_MD_CTX_free(mctx);
diff --git a/freebsd/crypto/openssl/crypto/dsa/dsa_ossl.c b/freebsd/crypto/openssl/crypto/dsa/dsa_ossl.c
index 09d2c440..b6834f5d 100644
--- a/freebsd/crypto/openssl/crypto/dsa/dsa_ossl.c
+++ b/freebsd/crypto/openssl/crypto/dsa/dsa_ossl.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -192,6 +192,12 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in,
return 0;
}
+ /* Reject obviously invalid parameters */
+ if (BN_is_zero(dsa->p) || BN_is_zero(dsa->q) || BN_is_zero(dsa->g)) {
+ DSAerr(DSA_F_DSA_SIGN_SETUP, DSA_R_INVALID_PARAMETERS);
+ return 0;
+ }
+
k = BN_new();
l = BN_new();
if (k == NULL || l == NULL)
diff --git a/freebsd/crypto/openssl/crypto/dsa/dsa_pmeth.c b/freebsd/crypto/openssl/crypto/dsa/dsa_pmeth.c
index 0e2dd54a..64aa8c29 100644
--- a/freebsd/crypto/openssl/crypto/dsa/dsa_pmeth.c
+++ b/freebsd/crypto/openssl/crypto/dsa/dsa_pmeth.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -22,8 +22,8 @@
typedef struct {
/* Parameter gen parameters */
- int nbits; /* size of p in bits (default: 1024) */
- int qbits; /* size of q in bits (default: 160) */
+ int nbits; /* size of p in bits (default: 2048) */
+ int qbits; /* size of q in bits (default: 224) */
const EVP_MD *pmd; /* MD for parameter generation */
/* Keygen callback info */
int gentmp[2];
@@ -37,8 +37,8 @@ static int pkey_dsa_init(EVP_PKEY_CTX *ctx)
if (dctx == NULL)
return 0;
- dctx->nbits = 1024;
- dctx->qbits = 160;
+ dctx->nbits = 2048;
+ dctx->qbits = 224;
dctx->pmd = NULL;
dctx->md = NULL;
@@ -140,7 +140,11 @@ static int pkey_dsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
EVP_MD_type((const EVP_MD *)p2) != NID_sha224 &&
EVP_MD_type((const EVP_MD *)p2) != NID_sha256 &&
EVP_MD_type((const EVP_MD *)p2) != NID_sha384 &&
- EVP_MD_type((const EVP_MD *)p2) != NID_sha512) {
+ EVP_MD_type((const EVP_MD *)p2) != NID_sha512 &&
+ EVP_MD_type((const EVP_MD *)p2) != NID_sha3_224 &&
+ EVP_MD_type((const EVP_MD *)p2) != NID_sha3_256 &&
+ EVP_MD_type((const EVP_MD *)p2) != NID_sha3_384 &&
+ EVP_MD_type((const EVP_MD *)p2) != NID_sha3_512) {
DSAerr(DSA_F_PKEY_DSA_CTRL, DSA_R_INVALID_DIGEST_TYPE);
return 0;
}
diff --git a/freebsd/crypto/openssl/crypto/ec/curve25519.c b/freebsd/crypto/openssl/crypto/ec/curve25519.c
index 8594d4e9..94d7a9e6 100644
--- a/freebsd/crypto/openssl/crypto/ec/curve25519.c
+++ b/freebsd/crypto/openssl/crypto/ec/curve25519.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -256,6 +256,7 @@ static void x25519_scalar_mulx(uint8_t out[32], const uint8_t scalar[32],
#if defined(X25519_ASM) \
|| ( (defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ == 16) \
&& !defined(__sparc__) \
+ && (!defined(__SIZEOF_LONG__) || (__SIZEOF_LONG__ == 8)) \
&& !(defined(__ANDROID__) && !defined(__clang__)) )
/*
* Base 2^51 implementation. It's virtually no different from reference
diff --git a/freebsd/crypto/openssl/crypto/ec/curve448/curve448.c b/freebsd/crypto/openssl/crypto/ec/curve448/curve448.c
index c7d3b29b..e85ace90 100644
--- a/freebsd/crypto/openssl/crypto/ec/curve448/curve448.c
+++ b/freebsd/crypto/openssl/crypto/ec/curve448/curve448.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2015-2016 Cryptography Research, Inc.
*
* Licensed under the OpenSSL license (the "License"). You may not use
@@ -29,8 +29,8 @@
static const curve448_scalar_t precomputed_scalarmul_adjustment = {
{
{
- SC_LIMB(0xc873d6d54a7bb0cf), SC_LIMB(0xe933d8d723a70aad),
- SC_LIMB(0xbb124b65129c96fd), SC_LIMB(0x00000008335dc163)
+ SC_LIMB(0xc873d6d54a7bb0cfULL), SC_LIMB(0xe933d8d723a70aadULL),
+ SC_LIMB(0xbb124b65129c96fdULL), SC_LIMB(0x00000008335dc163ULL)
}
}
};
diff --git a/freebsd/crypto/openssl/crypto/ec/curve448/curve448_tables.c b/freebsd/crypto/openssl/crypto/ec/curve448/curve448_tables.c
index 3a6e9fa6..2e95acb2 100644
--- a/freebsd/crypto/openssl/crypto/ec/curve448/curve448_tables.c
+++ b/freebsd/crypto/openssl/crypto/ec/curve448/curve448_tables.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2015-2016 Cryptography Research, Inc.
*
* Licensed under the OpenSSL license (the "License"). You may not use
@@ -18,325 +18,1045 @@
static const curve448_precomputed_s curve448_precomputed_base_table = {
{
{{
- {FIELD_LITERAL(0x00cc3b062366f4cc,0x003d6e34e314aa3c,0x00d51c0a7521774d,0x0094e060eec6ab8b,0x00d21291b4d80082,0x00befed12b55ef1e,0x00c3dd2df5c94518,0x00e0a7b112b8d4e6)},
- {FIELD_LITERAL(0x0019eb5608d8723a,0x00d1bab52fb3aedb,0x00270a7311ebc90c,0x0037c12b91be7f13,0x005be16cd8b5c704,0x003e181acda888e1,0x00bc1f00fc3fc6d0,0x00d3839bfa319e20)},
- {FIELD_LITERAL(0x003caeb88611909f,0x00ea8b378c4df3d4,0x00b3295b95a5a19a,0x00a65f97514bdfb5,0x00b39efba743cab1,0x0016ba98b862fd2d,0x0001508812ee71d7,0x000a75740eea114a)},
- }}, {{
- {FIELD_LITERAL(0x00ebcf0eb649f823,0x00166d332e98ea03,0x0059ddf64f5cd5f6,0x0047763123d9471b,0x00a64065c53ef62f,0x00978e44c480153d,0x000b5b2a0265f194,0x0046a24b9f32965a)},
- {FIELD_LITERAL(0x00b9eef787034df0,0x0020bc24de3390cd,0x000022160bae99bb,0x00ae66e886e97946,0x0048d4bbe02cbb8b,0x0072ba97b34e38d4,0x00eae7ec8f03e85a,0x005ba92ecf808b2c)},
- {FIELD_LITERAL(0x00c9cfbbe74258fd,0x00843a979ea9eaa7,0x000cbb4371cfbe90,0x0059bac8f7f0a628,0x004b3dff882ff530,0x0011869df4d90733,0x00595aa71f4abfc2,0x0070e2d38990c2e6)},
- }}, {{
- {FIELD_LITERAL(0x00de2010c0a01733,0x00c739a612e24297,0x00a7212643141d7c,0x00f88444f6b67c11,0x00484b7b16ec28f2,0x009c1b8856af9c68,0x00ff4669591fe9d6,0x0054974be08a32c8)},
- {FIELD_LITERAL(0x0010de3fd682ceed,0x008c07642d83ca4e,0x0013bb064e00a1cc,0x009411ae27870e11,0x00ea8e5b4d531223,0x0032fe7d2aaece2e,0x00d989e243e7bb41,0x000fe79a508e9b8b)},
- {FIELD_LITERAL(0x005e0426b9bfc5b1,0x0041a5b1d29ee4fa,0x0015b0def7774391,0x00bc164f1f51af01,0x00d543b0942797b9,0x003c129b6398099c,0x002b114c6e5adf18,0x00b4e630e4018a7b)},
- }}, {{
- {FIELD_LITERAL(0x00d490afc95f8420,0x00b096bf50c1d9b9,0x00799fd707679866,0x007c74d9334afbea,0x00efaa8be80ff4ed,0x0075c4943bb81694,0x00c21c2fca161f36,0x00e77035d492bfee)},
- {FIELD_LITERAL(0x006658a190dd6661,0x00e0e9bab38609a6,0x0028895c802237ed,0x006a0229c494f587,0x002dcde96c9916b7,0x00d158822de16218,0x00173b917a06856f,0x00ca78a79ae07326)},
- {FIELD_LITERAL(0x00e35bfc79caced4,0x0087238a3e1fe3bb,0x00bcbf0ff4ceff5b,0x00a19c1c94099b91,0x0071e102b49db976,0x0059e3d004eada1e,0x008da78afa58a47e,0x00579c8ebf269187)},
- }}, {{
- {FIELD_LITERAL(0x00a16c2905eee75f,0x009d4bcaea2c7e1d,0x00d3bd79bfad19df,0x0050da745193342c,0x006abdb8f6b29ab1,0x00a24fe0a4fef7ef,0x0063730da1057dfb,0x00a08c312c8eb108)},
- {FIELD_LITERAL(0x00b583be005375be,0x00a40c8f8a4e3df4,0x003fac4a8f5bdbf7,0x00d4481d872cd718,0x004dc8749cdbaefe,0x00cce740d5e5c975,0x000b1c1f4241fd21,0x00a76de1b4e1cd07)},
- {FIELD_LITERAL(0x007a076500d30b62,0x000a6e117b7f090f,0x00c8712ae7eebd9a,0x000fbd6c1d5f6ff7,0x003a7977246ebf11,0x00166ed969c6600e,0x00aa42e469c98bec,0x00dc58f307cf0666)},
- }}, {{
- {FIELD_LITERAL(0x004b491f65a9a28b,0x006a10309e8a55b7,0x00b67210185187ef,0x00cf6497b12d9b8f,0x0085778c56e2b1ba,0x0015b4c07a814d85,0x00686479e62da561,0x008de5d88f114916)},
- {FIELD_LITERAL(0x00e37c88d6bba7b1,0x003e4577e1b8d433,0x0050d8ea5f510ec0,0x0042fc9f2da9ef59,0x003bd074c1141420,0x00561b8b7b68774e,0x00232e5e5d1013a3,0x006b7f2cb3d7e73f)},
- {FIELD_LITERAL(0x004bdd0f0b41e6a0,0x001773057c405d24,0x006029f99915bd97,0x006a5ba70a17fe2f,0x0046111977df7e08,0x004d8124c89fb6b7,0x00580983b2bb2724,0x00207bf330d6f3fe)},
- }}, {{
- {FIELD_LITERAL(0x007efdc93972a48b,0x002f5e50e78d5fee,0x0080dc11d61c7fe5,0x0065aa598707245b,0x009abba2300641be,0x000c68787656543a,0x00ffe0fef2dc0a17,0x00007ffbd6cb4f3a)},
- {FIELD_LITERAL(0x0036012f2b836efc,0x00458c126d6b5fbc,0x00a34436d719ad1e,0x0097be6167117dea,0x0009c219c879cff3,0x0065564493e60755,0x00993ac94a8cdec0,0x002d4885a4d0dbaf)},
- {FIELD_LITERAL(0x00598b60b4c068ba,0x00c547a0be7f1afd,0x009582164acf12af,0x00af4acac4fbbe40,0x005f6ca7c539121a,0x003b6e752ebf9d66,0x00f08a30d5cac5d4,0x00e399bb5f97c5a9)},
- }}, {{
- {FIELD_LITERAL(0x007445a0409c0a66,0x00a65c369f3829c0,0x0031d248a4f74826,0x006817f34defbe8e,0x00649741d95ebf2e,0x00d46466ab16b397,0x00fdc35703bee414,0x00343b43334525f8)},
- {FIELD_LITERAL(0x001796bea93f6401,0x00090c5a42e85269,0x00672412ba1252ed,0x001201d47b6de7de,0x006877bccfe66497,0x00b554fd97a4c161,0x009753f42dbac3cf,0x00e983e3e378270a)},
- {FIELD_LITERAL(0x00ac3eff18849872,0x00f0eea3bff05690,0x00a6d72c21dd505d,0x001b832642424169,0x00a6813017b540e5,0x00a744bd71b385cd,0x0022a7d089130a7b,0x004edeec9a133486)},
- }}, {{
- {FIELD_LITERAL(0x00b2d6729196e8a9,0x0088a9bb2031cef4,0x00579e7787dc1567,0x0030f49feb059190,0x00a0b1d69c7f7d8f,0x0040bdcc6d9d806f,0x00d76c4037edd095,0x00bbf24376415dd7)},
- {FIELD_LITERAL(0x00240465ff5a7197,0x00bb97e76caf27d0,0x004b4edbf8116d39,0x001d8586f708cbaa,0x000f8ee8ff8e4a50,0x00dde5a1945dd622,0x00e6fc1c0957e07c,0x0041c9cdabfd88a0)},
- {FIELD_LITERAL(0x005344b0bf5b548c,0x002957d0b705cc99,0x00f586a70390553d,0x0075b3229f583cc3,0x00a1aa78227490e4,0x001bf09cf7957717,0x00cf6bf344325f52,0x0065bd1c23ca3ecf)},
- }}, {{
- {FIELD_LITERAL(0x009bff3b3239363c,0x00e17368796ef7c0,0x00528b0fe0971f3a,0x0008014fc8d4a095,0x00d09f2e8a521ec4,0x006713ab5dde5987,0x0003015758e0dbb1,0x00215999f1ba212d)},
- {FIELD_LITERAL(0x002c88e93527da0e,0x0077c78f3456aad5,0x0071087a0a389d1c,0x00934dac1fb96dbd,0x008470e801162697,0x005bc2196cd4ad49,0x00e535601d5087c3,0x00769888700f497f)},
- {FIELD_LITERAL(0x00da7a4b557298ad,0x0019d2589ea5df76,0x00ef3e38be0c6497,0x00a9644e1312609a,0x004592f61b2558da,0x0082c1df510d7e46,0x0042809a535c0023,0x00215bcb5afd7757)},
- }}, {{
- {FIELD_LITERAL(0x002b9df55a1a4213,0x00dcfc3b464a26be,0x00c4f9e07a8144d5,0x00c8e0617a92b602,0x008e3c93accafae0,0x00bf1bcb95b2ca60,0x004ce2426a613bf3,0x00266cac58e40921)},
- {FIELD_LITERAL(0x008456d5db76e8f0,0x0032ca9cab2ce163,0x0059f2b8bf91abcf,0x0063c2a021712788,0x00f86155af22f72d,0x00db98b2a6c005a0,0x00ac6e416a693ac4,0x007a93572af53226)},
- {FIELD_LITERAL(0x0087767520f0de22,0x0091f64012279fb5,0x001050f1f0644999,0x004f097a2477ad3c,0x006b37913a9947bd,0x001a3d78645af241,0x0057832bbb3008a7,0x002c1d902b80dc20)},
- }}, {{
- {FIELD_LITERAL(0x001a6002bf178877,0x009bce168aa5af50,0x005fc318ff04a7f5,0x0052818f55c36461,0x008768f5d4b24afb,0x0037ffbae7b69c85,0x0018195a4b61edc0,0x001e12ea088434b2)},
- {FIELD_LITERAL(0x0047d3f804e7ab07,0x00a809ab5f905260,0x00b3ffc7cdaf306d,0x00746e8ec2d6e509,0x00d0dade8887a645,0x00acceeebde0dd37,0x009bc2579054686b,0x0023804f97f1c2bf)},
- {FIELD_LITERAL(0x0043e2e2e50b80d7,0x00143aafe4427e0f,0x005594aaecab855b,0x008b12ccaaecbc01,0x002deeb091082bc3,0x009cca4be2ae7514,0x00142b96e696d047,0x00ad2a2b1c05256a)},
- }}, {{
- {FIELD_LITERAL(0x003914f2f144b78b,0x007a95dd8bee6f68,0x00c7f4384d61c8e6,0x004e51eb60f1bdb2,0x00f64be7aa4621d8,0x006797bfec2f0ac0,0x007d17aab3c75900,0x001893e73cac8bc5)},
- {FIELD_LITERAL(0x00140360b768665b,0x00b68aca4967f977,0x0001089b66195ae4,0x00fe71122185e725,0x000bca2618d49637,0x00a54f0557d7e98a,0x00cdcd2f91d6f417,0x00ab8c13741fd793)},
- {FIELD_LITERAL(0x00725ee6b1e549e0,0x007124a0769777fa,0x000b68fdad07ae42,0x0085b909cd4952df,0x0092d2e3c81606f4,0x009f22f6cac099a0,0x00f59da57f2799a8,0x00f06c090122f777)},
- }}, {{
- {FIELD_LITERAL(0x00ce0bed0a3532bc,0x001a5048a22df16b,0x00e31db4cbad8bf1,0x00e89292120cf00e,0x007d1dd1a9b00034,0x00e2a9041ff8f680,0x006a4c837ae596e7,0x00713af1068070b3)},
- {FIELD_LITERAL(0x00c4fe64ce66d04b,0x00b095d52e09b3d7,0x00758bbecb1a3a8e,0x00f35cce8d0650c0,0x002b878aa5984473,0x0062e0a3b7544ddc,0x00b25b290ed116fe,0x007b0f6abe0bebf2)},
- {FIELD_LITERAL(0x0081d4e3addae0a8,0x003410c836c7ffcc,0x00c8129ad89e4314,0x000e3d5a23922dcd,0x00d91e46f29c31f3,0x006c728cde8c5947,0x002bc655ba2566c0,0x002ca94721533108)},
- }}, {{
- {FIELD_LITERAL(0x0051e4b3f764d8a9,0x0019792d46e904a0,0x00853bc13dbc8227,0x000840208179f12d,0x0068243474879235,0x0013856fbfe374d0,0x00bda12fe8676424,0x00bbb43635926eb2)},
- {FIELD_LITERAL(0x0012cdc880a93982,0x003c495b21cd1b58,0x00b7e5c93f22a26e,0x0044aa82dfb99458,0x009ba092cdffe9c0,0x00a14b3ab2083b73,0x000271c2f70e1c4b,0x00eea9cac0f66eb8)},
- {FIELD_LITERAL(0x001a1847c4ac5480,0x00b1b412935bb03a,0x00f74285983bf2b2,0x00624138b5b5d0f1,0x008820c0b03d38bf,0x00b94e50a18c1572,0x0060f6934841798f,0x00c52f5d66d6ebe2)},
- }}, {{
- {FIELD_LITERAL(0x00da23d59f9bcea6,0x00e0f27007a06a4b,0x00128b5b43a6758c,0x000cf50190fa8b56,0x00fc877aba2b2d72,0x00623bef52edf53f,0x00e6af6b819669e2,0x00e314dc34fcaa4f)},
- {FIELD_LITERAL(0x0066e5eddd164d1e,0x00418a7c6fe28238,0x0002e2f37e962c25,0x00f01f56b5975306,0x0048842fa503875c,0x0057b0e968078143,0x00ff683024f3d134,0x0082ae28fcad12e4)},
- {FIELD_LITERAL(0x0011ddfd21260e42,0x00d05b0319a76892,0x00183ea4368e9b8f,0x00b0815662affc96,0x00b466a5e7ce7c88,0x00db93b07506e6ee,0x0033885f82f62401,0x0086f9090ec9b419)},
- }}, {{
- {FIELD_LITERAL(0x00d95d1c5fcb435a,0x0016d1ed6b5086f9,0x00792aa0b7e54d71,0x0067b65715f1925d,0x00a219755ec6176b,0x00bc3f026b12c28f,0x00700c897ffeb93e,0x0089b83f6ec50b46)},
- {FIELD_LITERAL(0x003c97e6384da36e,0x00423d53eac81a09,0x00b70d68f3cdce35,0x00ee7959b354b92c,0x00f4e9718819c8ca,0x009349f12acbffe9,0x005aee7b62cb7da6,0x00d97764154ffc86)},
- {FIELD_LITERAL(0x00526324babb46dc,0x002ee99b38d7bf9e,0x007ea51794706ef4,0x00abeb04da6e3c39,0x006b457c1d281060,0x00fe243e9a66c793,0x00378de0fb6c6ee4,0x003e4194b9c3cb93)},
- }}, {{
- {FIELD_LITERAL(0x00fed3cd80ca2292,0x0015b043a73ca613,0x000a9fd7bf9be227,0x003b5e03de2db983,0x005af72d46904ef7,0x00c0f1b5c49faa99,0x00dc86fc3bd305e1,0x00c92f08c1cb1797)},
- {FIELD_LITERAL(0x0079680ce111ed3b,0x001a1ed82806122c,0x000c2e7466d15df3,0x002c407f6f7150fd,0x00c5e7c96b1b0ce3,0x009aa44626863ff9,0x00887b8b5b80be42,0x00b6023cec964825)},
- {FIELD_LITERAL(0x00e4a8e1048970c8,0x0062887b7830a302,0x00bcf1c8cd81402b,0x0056dbb81a68f5be,0x0014eced83f12452,0x00139e1a510150df,0x00bb81140a82d1a3,0x000febcc1aaf1aa7)},
- }}, {{
- {FIELD_LITERAL(0x00a7527958238159,0x0013ec9537a84cd6,0x001d7fee7d562525,0x00b9eefa6191d5e5,0x00dbc97db70bcb8a,0x00481affc7a4d395,0x006f73d3e70c31bb,0x00183f324ed96a61)},
- {FIELD_LITERAL(0x0039dd7ce7fc6860,0x00d64f6425653da1,0x003e037c7f57d0af,0x0063477a06e2bcf2,0x001727dbb7ac67e6,0x0049589f5efafe2e,0x00fc0fef2e813d54,0x008baa5d087fb50d)},
- {FIELD_LITERAL(0x0024fb59d9b457c7,0x00a7d4e060223e4c,0x00c118d1b555fd80,0x0082e216c732f22a,0x00cd2a2993089504,0x003638e836a3e13d,0x000d855ee89b4729,0x008ec5b7d4810c91)},
- }}, {{
- {FIELD_LITERAL(0x001bf51f7d65cdfd,0x00d14cdafa16a97d,0x002c38e60fcd10e7,0x00a27446e393efbd,0x000b5d8946a71fdd,0x0063df2cde128f2f,0x006c8679569b1888,0x0059ffc4925d732d)},
- {FIELD_LITERAL(0x00ece96f95f2b66f,0x00ece7952813a27b,0x0026fc36592e489e,0x007157d1a2de0f66,0x00759dc111d86ddf,0x0012881e5780bb0f,0x00c8ccc83ad29496,0x0012b9bd1929eb71)},
- {FIELD_LITERAL(0x000fa15a20da5df0,0x00349ddb1a46cd31,0x002c512ad1d8e726,0x00047611f669318d,0x009e68fba591e17e,0x004320dffa803906,0x00a640874951a3d3,0x00b6353478baa24f)},
- }}, {{
- {FIELD_LITERAL(0x009696510000d333,0x00ec2f788bc04826,0x000e4d02b1f67ba5,0x00659aa8dace08b6,0x00d7a38a3a3ae533,0x008856defa8c746b,0x004d7a4402d3da1a,0x00ea82e06229260f)},
- {FIELD_LITERAL(0x006a15bb20f75c0c,0x0079a144027a5d0c,0x00d19116ce0b4d70,0x0059b83bcb0b268e,0x005f58f63f16c127,0x0079958318ee2c37,0x00defbb063d07f82,0x00f1f0b931d2d446)},
- {FIELD_LITERAL(0x00cb5e4c3c35d422,0x008df885ca43577f,0x00fa50b16ca3e471,0x005a0e58e17488c8,0x00b2ceccd6d34d19,0x00f01d5d235e36e9,0x00db2e7e4be6ca44,0x00260ab77f35fccd)},
- }}, {{
- {FIELD_LITERAL(0x006f6fd9baac61d5,0x002a7710a020a895,0x009de0db7fc03d4d,0x00cdedcb1875f40b,0x00050caf9b6b1e22,0x005e3a6654456ab0,0x00775fdf8c4423d4,0x0028701ea5738b5d)},
- {FIELD_LITERAL(0x009ffd90abfeae96,0x00cba3c2b624a516,0x005ef08bcee46c91,0x00e6fde30afb6185,0x00f0b4db4f818ce4,0x006c54f45d2127f5,0x00040125035854c7,0x00372658a3287e13)},
- {FIELD_LITERAL(0x00d7070fb1beb2ab,0x0078fc845a93896b,0x006894a4b2f224a6,0x005bdd8192b9dbde,0x00b38839874b3a9e,0x00f93618b04b7a57,0x003e3ec75fd2c67e,0x00bf5e6bfc29494a)},
- }}, {{
- {FIELD_LITERAL(0x00f19224ebba2aa5,0x0074f89d358e694d,0x00eea486597135ad,0x0081579a4555c7e1,0x0010b9b872930a9d,0x00f002e87a30ecc0,0x009b9d66b6de56e2,0x00a3c4f45e8004eb)},
- {FIELD_LITERAL(0x0045e8dda9400888,0x002ff12e5fc05db7,0x00a7098d54afe69c,0x00cdbe846a500585,0x00879c1593ca1882,0x003f7a7fea76c8b0,0x002cd73dd0c8e0a1,0x00645d6ce96f51fe)},
- {FIELD_LITERAL(0x002b7e83e123d6d6,0x00398346f7419c80,0x0042922e55940163,0x005e7fc5601886a3,0x00e88f2cee1d3103,0x00e7fab135f2e377,0x00b059984dbf0ded,0x0009ce080faa5bb8)},
- }}, {{
- {FIELD_LITERAL(0x0085e78af7758979,0x00275a4ee1631a3a,0x00d26bc0ed78b683,0x004f8355ea21064f,0x00d618e1a32696e5,0x008d8d7b150e5680,0x00a74cd854b278d2,0x001dd62702203ea0)},
- {FIELD_LITERAL(0x00f89335c2a59286,0x00a0f5c905d55141,0x00b41fb836ee9382,0x00e235d51730ca43,0x00a5cb37b5c0a69a,0x009b966ffe136c45,0x00cb2ea10bf80ed1,0x00fb2b370b40dc35)},
- {FIELD_LITERAL(0x00d687d16d4ee8ba,0x0071520bdd069dff,0x00de85c60d32355d,0x0087d2e3565102f4,0x00cde391b8dfc9aa,0x00e18d69efdfefe5,0x004a9d0591954e91,0x00fa36dd8b50eee5)},
- }}, {{
- {FIELD_LITERAL(0x002e788749a865f7,0x006e4dc3116861ea,0x009f1428c37276e6,0x00e7d2e0fc1e1226,0x003aeebc6b6c45f6,0x0071a8073bf500c9,0x004b22ad986b530c,0x00f439e63c0d79d4)},
- {FIELD_LITERAL(0x006bc3d53011f470,0x00032d6e692b83e8,0x00059722f497cd0b,0x0009b4e6f0c497cc,0x0058a804b7cce6c0,0x002b71d3302bbd5d,0x00e2f82a36765fce,0x008dded99524c703)},
- {FIELD_LITERAL(0x004d058953747d64,0x00701940fe79aa6f,0x00a620ac71c760bf,0x009532b611158b75,0x00547ed7f466f300,0x003cb5ab53a8401a,0x00c7763168ce3120,0x007e48e33e4b9ab2)},
- }}, {{
- {FIELD_LITERAL(0x001b2fc57bf3c738,0x006a3f918993fb80,0x0026f7a14fdec288,0x0075a2cdccef08db,0x00d3ecbc9eecdbf1,0x0048c40f06e5bf7f,0x00d63e423009896b,0x000598bc99c056a8)},
- {FIELD_LITERAL(0x002f194eaafa46dc,0x008e38f57fe87613,0x00dc8e5ae25f4ab2,0x000a17809575e6bd,0x00d3ec7923ba366a,0x003a7e72e0ad75e3,0x0010024b88436e0a,0x00ed3c5444b64051)},
- {FIELD_LITERAL(0x00831fc1340af342,0x00c9645669466d35,0x007692b4cc5a080f,0x009fd4a47ac9259f,0x001eeddf7d45928b,0x003c0446fc45f28b,0x002c0713aa3e2507,0x0095706935f0f41e)},
- }}, {{
- {FIELD_LITERAL(0x00766ae4190ec6d8,0x0065768cabc71380,0x00b902598416cdc2,0x00380021ad38df52,0x008f0b89d6551134,0x004254d4cc62c5a5,0x000d79f4484b9b94,0x00b516732ae3c50e)},
- {FIELD_LITERAL(0x001fb73475c45509,0x00d2b2e5ea43345a,0x00cb3c3842077bd1,0x0029f90ad820946e,0x007c11b2380778aa,0x009e54ece62c1704,0x004bc60c41ca01c3,0x004525679a5a0b03)},
- {FIELD_LITERAL(0x00c64fbddbed87b3,0x0040601d11731faa,0x009c22475b6f9d67,0x0024b79dae875f15,0x00616fed3f02c3b0,0x0000cf39f6af2d3b,0x00c46bac0aa9a688,0x00ab23e2800da204)},
- }}, {{
- {FIELD_LITERAL(0x000b3a37617632b0,0x00597199fe1cfb6c,0x0042a7ccdfeafdd6,0x004cc9f15ebcea17,0x00f436e596a6b4a4,0x00168861142df0d8,0x000753edfec26af5,0x000c495d7e388116)},
- {FIELD_LITERAL(0x0017085f4a346148,0x00c7cf7a37f62272,0x001776e129bc5c30,0x009955134c9eef2a,0x001ba5bdf1df07be,0x00ec39497103a55c,0x006578354fda6cfb,0x005f02719d4f15ee)},
- {FIELD_LITERAL(0x0052b9d9b5d9655d,0x00d4ec7ba1b461c3,0x00f95df4974f280b,0x003d8e5ca11aeb51,0x00d4981eb5a70b26,0x000af9a4f6659f29,0x004598c846faeb43,0x0049d9a183a47670)},
- }}, {{
- {FIELD_LITERAL(0x000a72d23dcb3f1f,0x00a3737f84011727,0x00f870c0fbbf4a47,0x00a7aadd04b5c9ca,0x000c7715c67bd072,0x00015a136afcd74e,0x0080d5caea499634,0x0026b448ec7514b7)},
- {FIELD_LITERAL(0x00b60167d9e7d065,0x00e60ba0d07381e8,0x003a4f17b725c2d4,0x006c19fe176b64fa,0x003b57b31af86ccb,0x0021047c286180fd,0x00bdc8fb00c6dbb6,0x00fe4a9f4bab4f3f)},
- {FIELD_LITERAL(0x0088ffc3a16111f7,0x009155e4245d0bc8,0x00851d68220572d5,0x00557ace1e514d29,0x0031d7c339d91022,0x00101d0ae2eaceea,0x00246ab3f837b66a,0x00d5216d381ff530)},
- }}, {{
- {FIELD_LITERAL(0x0057e7ea35f36dae,0x00f47d7ad15de22e,0x00d757ea4b105115,0x008311457d579d7e,0x00b49b75b1edd4eb,0x0081c7ff742fd63a,0x00ddda3187433df6,0x00475727d55f9c66)},
- {FIELD_LITERAL(0x00a6295218dc136a,0x00563b3af0e9c012,0x00d3753b0145db1b,0x004550389c043dc1,0x00ea94ae27401bdf,0x002b0b949f2b7956,0x00c63f780ad8e23c,0x00e591c47d6bab15)},
- {FIELD_LITERAL(0x00416c582b058eb6,0x004107da5b2cc695,0x00b3cd2556aeec64,0x00c0b418267e57a1,0x001799293579bd2e,0x0046ed44590e4d07,0x001d7459b3630a1e,0x00c6afba8b6696aa)},
- }}, {{
- {FIELD_LITERAL(0x008d6009b26da3f8,0x00898e88ca06b1ca,0x00edb22b2ed7fe62,0x00fbc93516aabe80,0x008b4b470c42ce0d,0x00e0032ba7d0dcbb,0x00d76da3a956ecc8,0x007f20fe74e3852a)},
- {FIELD_LITERAL(0x002419222c607674,0x00a7f23af89188b3,0x00ad127284e73d1c,0x008bba582fae1c51,0x00fc6aa7ca9ecab1,0x003df5319eb6c2ba,0x002a05af8a8b199a,0x004bf8354558407c)},
- {FIELD_LITERAL(0x00ce7d4a30f0fcbf,0x00d02c272629f03d,0x0048c001f7400bc2,0x002c21368011958d,0x0098a550391e96b5,0x002d80b66390f379,0x001fa878760cc785,0x001adfce54b613d5)},
- }}, {{
- {FIELD_LITERAL(0x001ed4dc71fa2523,0x005d0bff19bf9b5c,0x00c3801cee065a64,0x001ed0b504323fbf,0x0003ab9fdcbbc593,0x00df82070178b8d2,0x00a2bcaa9c251f85,0x00c628a3674bd02e)},
- {FIELD_LITERAL(0x006b7a0674f9f8de,0x00a742414e5c7cff,0x0041cbf3c6e13221,0x00e3a64fd207af24,0x0087c05f15fbe8d1,0x004c50936d9e8a33,0x001306ec21042b6d,0x00a4f4137d1141c2)},
- {FIELD_LITERAL(0x0009e6fb921568b0,0x00b3c60120219118,0x002a6c3460dd503a,0x009db1ef11654b54,0x0063e4bf0be79601,0x00670d34bb2592b9,0x00dcee2f6c4130ce,0x00b2682e88e77f54)},
- }}, {{
- {FIELD_LITERAL(0x000d5b4b3da135ab,0x00838f3e5064d81d,0x00d44eb50f6d94ed,0x0008931ab502ac6d,0x00debe01ca3d3586,0x0025c206775f0641,0x005ad4b6ae912763,0x007e2c318ad8f247)},
- {FIELD_LITERAL(0x00ddbe0750dd1add,0x004b3c7b885844b8,0x00363e7ecf12f1ae,0x0062e953e6438f9d,0x0023cc73b076afe9,0x00b09fa083b4da32,0x00c7c3d2456c541d,0x005b591ec6b694d4)},
- {FIELD_LITERAL(0x0028656e19d62fcf,0x0052a4af03df148d,0x00122765ddd14e42,0x00f2252904f67157,0x004741965b636f3a,0x006441d296132cb9,0x005e2106f956a5b7,0x00247029592d335c)},
- }}, {{
- {FIELD_LITERAL(0x003fe038eb92f894,0x000e6da1b72e8e32,0x003a1411bfcbe0fa,0x00b55d473164a9e4,0x00b9a775ac2df48d,0x0002ddf350659e21,0x00a279a69eb19cb3,0x00f844eab25cba44)},
- {FIELD_LITERAL(0x00c41d1f9c1f1ac1,0x007b2df4e9f19146,0x00b469355fd5ba7a,0x00b5e1965afc852a,0x00388d5f1e2d8217,0x0022079e4c09ae93,0x0014268acd4ef518,0x00c1dd8d9640464c)},
- {FIELD_LITERAL(0x0038526adeed0c55,0x00dd68c607e3fe85,0x00f746ddd48a5d57,0x0042f2952b963b7c,0x001cbbd6876d5ec2,0x005e341470bca5c2,0x00871d41e085f413,0x00e53ab098f45732)},
- }}, {{
- {FIELD_LITERAL(0x004d51124797c831,0x008f5ae3750347ad,0x0070ced94c1a0c8e,0x00f6db2043898e64,0x000d00c9a5750cd0,0x000741ec59bad712,0x003c9d11aab37b7f,0x00a67ba169807714)},
- {FIELD_LITERAL(0x00adb2c1566e8b8f,0x0096c68a35771a9a,0x00869933356f334a,0x00ba9c93459f5962,0x009ec73fb6e8ca4b,0x003c3802c27202e1,0x0031f5b733e0c008,0x00f9058c19611fa9)},
- {FIELD_LITERAL(0x00238f01814a3421,0x00c325a44b6cce28,0x002136f97aeb0e73,0x000cac8268a4afe2,0x0022fd218da471b3,0x009dcd8dfff8def9,0x00cb9f8181d999bb,0x00143ae56edea349)},
- }}, {{
- {FIELD_LITERAL(0x0000623bf87622c5,0x00a1966fdd069496,0x00c315b7b812f9fc,0x00bdf5efcd128b97,0x001d464f532e3e16,0x003cd94f081bfd7e,0x00ed9dae12ce4009,0x002756f5736eee70)},
- {FIELD_LITERAL(0x00a5187e6ee7341b,0x00e6d52e82d83b6e,0x00df3c41323094a7,0x00b3324f444e9de9,0x00689eb21a35bfe5,0x00f16363becd548d,0x00e187cc98e7f60f,0x00127d9062f0ccab)},
- {FIELD_LITERAL(0x004ad71b31c29e40,0x00a5fcace12fae29,0x004425b5597280ed,0x00e7ef5d716c3346,0x0010b53ada410ac8,0x0092310226060c9b,0x0091c26128729c7e,0x0088b42900f8ec3b)},
- }}, {{
- {FIELD_LITERAL(0x00f1e26e9762d4a8,0x00d9d74082183414,0x00ffec9bd57a0282,0x000919e128fd497a,0x00ab7ae7d00fe5f8,0x0054dc442851ff68,0x00c9ebeb3b861687,0x00507f7cab8b698f)},
- {FIELD_LITERAL(0x00c13c5aae3ae341,0x009c6c9ed98373e7,0x00098f26864577a8,0x0015b886e9488b45,0x0037692c42aadba5,0x00b83170b8e7791c,0x001670952ece1b44,0x00fd932a39276da2)},
- {FIELD_LITERAL(0x0081a3259bef3398,0x005480fff416107b,0x00ce4f607d21be98,0x003ffc084b41df9b,0x0043d0bb100502d1,0x00ec35f575ba3261,0x00ca18f677300ef3,0x00e8bb0a827d8548)},
- }}, {{
- {FIELD_LITERAL(0x00df76b3328ada72,0x002e20621604a7c2,0x00f910638a105b09,0x00ef4724d96ef2cd,0x00377d83d6b8a2f7,0x00b4f48805ade324,0x001cd5da8b152018,0x0045af671a20ca7f)},
- {FIELD_LITERAL(0x009ae3b93a56c404,0x004a410b7a456699,0x00023a619355e6b2,0x009cdc7297387257,0x0055b94d4ae70d04,0x002cbd607f65b005,0x003208b489697166,0x00ea2aa058867370)},
- {FIELD_LITERAL(0x00f29d2598ee3f32,0x00b4ac5385d82adc,0x007633eaf04df19b,0x00aa2d3d77ceab01,0x004a2302fcbb778a,0x00927f225d5afa34,0x004a8e9d5047f237,0x008224ae9dbce530)},
- }}, {{
- {FIELD_LITERAL(0x001cf640859b02f8,0x00758d1d5d5ce427,0x00763c784ef4604c,0x005fa81aee205270,0x00ac537bfdfc44cb,0x004b919bd342d670,0x00238508d9bf4b7a,0x00154888795644f3)},
- {FIELD_LITERAL(0x00c845923c084294,0x00072419a201bc25,0x0045f408b5f8e669,0x00e9d6a186b74dfe,0x00e19108c68fa075,0x0017b91d874177b7,0x002f0ca2c7912c5a,0x009400aa385a90a2)},
- {FIELD_LITERAL(0x0071110b01482184,0x00cfed0044f2bef8,0x0034f2901cf4662e,0x003b4ae2a67f9834,0x00cca9b96fe94810,0x00522507ae77abd0,0x00bac7422721e73e,0x0066622b0f3a62b0)},
- }}, {{
- {FIELD_LITERAL(0x00f8ac5cf4705b6a,0x00867d82dcb457e3,0x007e13ab2ccc2ce9,0x009ee9a018d3930e,0x008370f8ecb42df8,0x002d9f019add263e,0x003302385b92d196,0x00a15654536e2c0c)},
- {FIELD_LITERAL(0x0026ef1614e160af,0x00c023f9edfc9c76,0x00cff090da5f57ba,0x0076db7a66643ae9,0x0019462f8c646999,0x008fec00b3854b22,0x00d55041692a0a1c,0x0065db894215ca00)},
- {FIELD_LITERAL(0x00a925036e0a451c,0x002a0390c36b6cc1,0x00f27020d90894f4,0x008d90d52cbd3d7f,0x00e1d0137392f3b8,0x00f017c158b51a8f,0x00cac313d3ed7dbc,0x00b99a81e3eb42d3)},
- }}, {{
- {FIELD_LITERAL(0x00b54850275fe626,0x0053a3fd1ec71140,0x00e3d2d7dbe096fa,0x00e4ac7b595cce4c,0x0077bad449c0a494,0x00b7c98814afd5b3,0x0057226f58486cf9,0x00b1557154f0cc57)},
- {FIELD_LITERAL(0x008cc9cd236315c0,0x0031d9c5b39fda54,0x00a5713ef37e1171,0x00293d5ae2886325,0x00c4aba3e05015e1,0x0003f35ef78e4fc6,0x0039d6bd3ac1527b,0x0019d7c3afb77106)},
- {FIELD_LITERAL(0x007b162931a985af,0x00ad40a2e0daa713,0x006df27c4009f118,0x00503e9f4e2e8bec,0x00751a77c82c182d,0x000298937769245b,0x00ffb1e8fabf9ee5,0x0008334706e09abe)},
- }}, {{
- {FIELD_LITERAL(0x00dbca4e98a7dcd9,0x00ee29cfc78bde99,0x00e4a3b6995f52e9,0x0045d70189ae8096,0x00fd2a8a3b9b0d1b,0x00af1793b107d8e1,0x00dbf92cbe4afa20,0x00da60f798e3681d)},
- {FIELD_LITERAL(0x004246bfcecc627a,0x004ba431246c03a4,0x00bd1d101872d497,0x003b73d3f185ee16,0x001feb2e2678c0e3,0x00ff13c5a89dec76,0x00ed06042e771d8f,0x00a4fd2a897a83dd)},
- {FIELD_LITERAL(0x009a4a3be50d6597,0x00de3165fc5a1096,0x004f3f56e345b0c7,0x00f7bf721d5ab8bc,0x004313e47b098c50,0x00e4c7d5c0e1adbb,0x002e3e3db365051e,0x00a480c2cd6a96fb)},
- }}, {{
- {FIELD_LITERAL(0x00417fa30a7119ed,0x00af257758419751,0x00d358a487b463d4,0x0089703cc720b00d,0x00ce56314ff7f271,0x0064db171ade62c1,0x00640b36d4a22fed,0x00424eb88696d23f)},
- {FIELD_LITERAL(0x004ede34af2813f3,0x00d4a8e11c9e8216,0x004796d5041de8a5,0x00c4c6b4d21cc987,0x00e8a433ee07fa1e,0x0055720b5abcc5a1,0x008873ea9c74b080,0x005b3fec1ab65d48)},
- {FIELD_LITERAL(0x0047e5277db70ec5,0x000a096c66db7d6b,0x00b4164cc1730159,0x004a9f783fe720fe,0x00a8177b94449dbc,0x0095a24ff49a599f,0x0069c1c578250cbc,0x00452019213debf4)},
- }}, {{
- {FIELD_LITERAL(0x0021ce99e09ebda3,0x00fcbd9f91875ad0,0x009bbf6b7b7a0b5f,0x00388886a69b1940,0x00926a56d0f81f12,0x00e12903c3358d46,0x005dfce4e8e1ce9d,0x0044cfa94e2f7e23)},
- {FIELD_LITERAL(0x001bd59c09e982ea,0x00f72daeb937b289,0x0018b76dca908e0e,0x00edb498512384ad,0x00ce0243b6cc9538,0x00f96ff690cb4e70,0x007c77bf9f673c8d,0x005bf704c088a528)},
- {FIELD_LITERAL(0x0093d4628dcb33be,0x0095263d51d42582,0x0049b3222458fe06,0x00e7fce73b653a7f,0x003ca2ebce60b369,0x00c5de239a32bea4,0x0063b8b3d71fb6bf,0x0039aeeb78a1a839)},
- }}, {{
- {FIELD_LITERAL(0x007dc52da400336c,0x001fded1e15b9457,0x00902e00f5568e3a,0x00219bef40456d2d,0x005684161fb3dbc9,0x004a4e9be49a76ea,0x006e685ae88b78ff,0x0021c42f13042d3c)},
- {FIELD_LITERAL(0x00fb22bb5fd3ce50,0x0017b48aada7ae54,0x00fd5c44ad19a536,0x000ccc4e4e55e45c,0x00fd637d45b4c3f5,0x0038914e023c37cf,0x00ac1881d6a8d898,0x00611ed8d3d943a8)},
- {FIELD_LITERAL(0x0056e2259d113d2b,0x00594819b284ec16,0x00c7bf794bb36696,0x00721ee75097cdc6,0x00f71be9047a2892,0x00df6ba142564edf,0x0069580b7a184e8d,0x00f056e38fca0fee)},
- }}, {{
- {FIELD_LITERAL(0x009df98566a18c6d,0x00cf3a200968f219,0x0044ba60da6d9086,0x00dbc9c0e344da03,0x000f9401c4466855,0x00d46a57c5b0a8d1,0x00875a635d7ac7c6,0x00ef4a933b7e0ae6)},
- {FIELD_LITERAL(0x005e8694077a1535,0x008bef75f71c8f1d,0x000a7c1316423511,0x00906e1d70604320,0x003fc46c1a2ffbd6,0x00d1d5022e68f360,0x002515fba37bbf46,0x00ca16234e023b44)},
- {FIELD_LITERAL(0x00787c99561f4690,0x00a857a8c1561f27,0x00a10df9223c09fe,0x00b98a9562e3b154,0x004330b8744c3ed2,0x00e06812807ec5c4,0x00e4cf6a7db9f1e3,0x00d95b089f132a34)},
- }}, {{
- {FIELD_LITERAL(0x002922b39ca33eec,0x0090d12a5f3ab194,0x00ab60c02fb5f8ed,0x00188d292abba1cf,0x00e10edec9698f6e,0x0069a4d9934133c8,0x0024aac40e6d3d06,0x001702c2177661b0)},
- {FIELD_LITERAL(0x00139078397030bd,0x000e3c447e859a00,0x0064a5b334c82393,0x00b8aabeb7358093,0x00020778bb9ae73b,0x0032ee94c7892a18,0x008215253cb41bda,0x005e2797593517ae)},
- {FIELD_LITERAL(0x0083765a5f855d4a,0x0051b6d1351b8ee2,0x00116de548b0f7bb,0x0087bd88703affa0,0x0095b2cc34d7fdd2,0x0084cd81b53f0bc8,0x008562fc995350ed,0x00a39abb193651e3)},
- }}, {{
- {FIELD_LITERAL(0x0019e23f0474b114,0x00eb94c2ad3b437e,0x006ddb34683b75ac,0x00391f9209b564c6,0x00083b3bb3bff7aa,0x00eedcd0f6dceefc,0x00b50817f794fe01,0x0036474deaaa75c9)},
- {FIELD_LITERAL(0x0091868594265aa2,0x00797accae98ca6d,0x0008d8c5f0f8a184,0x00d1f4f1c2b2fe6e,0x0036783dfb48a006,0x008c165120503527,0x0025fd780058ce9b,0x0068beb007be7d27)},
- {FIELD_LITERAL(0x00d0ff88aa7c90c2,0x00b2c60dacf53394,0x0094a7284d9666d6,0x00bed9022ce7a19d,0x00c51553f0cd7682,0x00c3fb870b124992,0x008d0bc539956c9b,0x00fc8cf258bb8885)},
- }}, {{
- {FIELD_LITERAL(0x003667bf998406f8,0x0000115c43a12975,0x001e662f3b20e8fd,0x0019ffa534cb24eb,0x00016be0dc8efb45,0x00ff76a8b26243f5,0x00ae20d241a541e3,0x0069bd6af13cd430)},
- {FIELD_LITERAL(0x0045fdc16487cda3,0x00b2d8e844cf2ed7,0x00612c50e88c1607,0x00a08aabc66c1672,0x006031fdcbb24d97,0x001b639525744b93,0x004409d62639ab17,0x00a1853d0347ab1d)},
- {FIELD_LITERAL(0x0075a1a56ebf5c21,0x00a3e72be9ac53ed,0x00efcde1629170c2,0x0004225fe91ef535,0x0088049fc73dfda7,0x004abc74857e1288,0x0024e2434657317c,0x00d98cb3d3e5543c)},
- }}, {{
- {FIELD_LITERAL(0x00b4b53eab6bdb19,0x009b22d8b43711d0,0x00d948b9d961785d,0x00cb167b6f279ead,0x00191de3a678e1c9,0x00d9dd9511095c2e,0x00f284324cd43067,0x00ed74fa535151dd)},
- {FIELD_LITERAL(0x007e32c049b5c477,0x009d2bfdbd9bcfd8,0x00636e93045938c6,0x007fde4af7687298,0x0046a5184fafa5d3,0x0079b1e7f13a359b,0x00875adf1fb927d6,0x00333e21c61bcad2)},
- {FIELD_LITERAL(0x00048014f73d8b8d,0x0075684aa0966388,0x0092be7df06dc47c,0x0097cebcd0f5568a,0x005a7004d9c4c6a9,0x00b0ecbb659924c7,0x00d90332dd492a7c,0x0057fc14df11493d)},
- }}, {{
- {FIELD_LITERAL(0x0008ed8ea0ad95be,0x0041d324b9709645,0x00e25412257a19b4,0x0058df9f3423d8d2,0x00a9ab20def71304,0x009ae0dbf8ac4a81,0x00c9565977e4392a,0x003c9269444baf55)},
- {FIELD_LITERAL(0x007df6cbb926830b,0x00d336058ae37865,0x007af47dac696423,0x0048d3011ec64ac8,0x006b87666e40049f,0x0036a2e0e51303d7,0x00ba319bd79dbc55,0x003e2737ecc94f53)},
- {FIELD_LITERAL(0x00d296ff726272d9,0x00f6d097928fcf57,0x00e0e616a55d7013,0x00deaf454ed9eac7,0x0073a56bedef4d92,0x006ccfdf6fc92e19,0x009d1ee1371a7218,0x00ee3c2ee4462d80)},
- }}, {{
- {FIELD_LITERAL(0x00437bce9bccdf9d,0x00e0c8e2f85dc0a3,0x00c91a7073995a19,0x00856ec9fe294559,0x009e4b33394b156e,0x00e245b0dc497e5c,0x006a54e687eeaeff,0x00f1cd1cd00fdb7c)},
- {FIELD_LITERAL(0x008132ae5c5d8cd1,0x00121d68324a1d9f,0x00d6be9dafcb8c76,0x00684d9070edf745,0x00519fbc96d7448e,0x00388182fdc1f27e,0x000235baed41f158,0x00bf6cf6f1a1796a)},
- {FIELD_LITERAL(0x002adc4b4d148219,0x003084ada0d3a90a,0x0046de8aab0f2e4e,0x00452d342a67b5fd,0x00d4b50f01d4de21,0x00db6d9fc0cefb79,0x008c184c86a462cd,0x00e17c83764d42da)},
- }}, {{
- {FIELD_LITERAL(0x007b2743b9a1e01a,0x007847ffd42688c4,0x006c7844d610a316,0x00f0cb8b250aa4b0,0x00a19060143b3ae6,0x0014eb10b77cfd80,0x000170905729dd06,0x00063b5b9cd72477)},
- {FIELD_LITERAL(0x00ce382dc7993d92,0x00021153e938b4c8,0x00096f7567f48f51,0x0058f81ddfe4b0d5,0x00cc379a56b355c7,0x002c760770d3e819,0x00ee22d1d26e5a40,0x00de6d93d5b082d7)},
- {FIELD_LITERAL(0x000a91a42c52e056,0x00185f6b77fce7ea,0x000803c51962f6b5,0x0022528582ba563d,0x0043f8040e9856d6,0x0085a29ec81fb860,0x005f9a611549f5ff,0x00c1f974ecbd4b06)},
- }}, {{
- {FIELD_LITERAL(0x005b64c6fd65ec97,0x00c1fdd7f877bc7f,0x000d9cc6c89f841c,0x005c97b7f1aff9ad,0x0075e3c61475d47e,0x001ecb1ba8153011,0x00fe7f1c8d71d40d,0x003fa9757a229832)},
- {FIELD_LITERAL(0x00ffc5c89d2b0cba,0x00d363d42e3e6fc3,0x0019a1a0118e2e8a,0x00f7baeff48882e1,0x001bd5af28c6b514,0x0055476ca2253cb2,0x00d8eb1977e2ddf3,0x00b173b1adb228a1)},
- {FIELD_LITERAL(0x00f2cb99dd0ad707,0x00e1e08b6859ddd8,0x000008f2d0650bcc,0x00d7ed392f8615c3,0x00976750a94da27f,0x003e83bb0ecb69ba,0x00df8e8d15c14ac6,0x00f9f7174295d9c2)},
- }}, {{
- {FIELD_LITERAL(0x00f11cc8e0e70bcb,0x00e5dc689974e7dd,0x0014e409f9ee5870,0x00826e6689acbd63,0x008a6f4e3d895d88,0x00b26a8da41fd4ad,0x000fb7723f83efd7,0x009c749db0a5f6c3)},
- {FIELD_LITERAL(0x002389319450f9ba,0x003677f31aa1250a,0x0092c3db642f38cb,0x00f8b64c0dfc9773,0x00cd49fe3505b795,0x0068105a4090a510,0x00df0ba2072a8bb6,0x00eb396143afd8be)},
- {FIELD_LITERAL(0x00a0d4ecfb24cdff,0x00ddaf8008ba6479,0x00f0b3e36d4b0f44,0x003734bd3af1f146,0x00b87e2efc75527e,0x00d230df55ddab50,0x002613257ae56c1d,0x00bc0946d135934d)},
- }}, {{
- {FIELD_LITERAL(0x00468711bd994651,0x0033108fa67561bf,0x0089d760192a54b4,0x00adc433de9f1871,0x000467d05f36e050,0x007847e0f0579f7f,0x00a2314ad320052d,0x00b3a93649f0b243)},
- {FIELD_LITERAL(0x0067f8f0c4fe26c9,0x0079c4a3cc8f67b9,0x0082b1e62f23550d,0x00f2d409caefd7f5,0x0080e67dcdb26e81,0x0087ae993ea1f98a,0x00aa108becf61d03,0x001acf11efb608a3)},
- {FIELD_LITERAL(0x008225febbab50d9,0x00f3b605e4dd2083,0x00a32b28189e23d2,0x00d507e5e5eb4c97,0x005a1a84e302821f,0x0006f54c1c5f08c7,0x00a347c8cb2843f0,0x0009f73e9544bfa5)},
- }}, {{
- {FIELD_LITERAL(0x006c59c9ae744185,0x009fc32f1b4282cd,0x004d6348ca59b1ac,0x00105376881be067,0x00af4096013147dc,0x004abfb5a5cb3124,0x000d2a7f8626c354,0x009c6ed568e07431)},
- {FIELD_LITERAL(0x00e828333c297f8b,0x009ef3cf8c3f7e1f,0x00ab45f8fff31cb9,0x00c8b4178cb0b013,0x00d0c50dd3260a3f,0x0097126ac257f5bc,0x0042376cc90c705a,0x001d96fdb4a1071e)},
- {FIELD_LITERAL(0x00542d44d89ee1a8,0x00306642e0442d98,0x0090853872b87338,0x002362cbf22dc044,0x002c222adff663b8,0x0067c924495fcb79,0x000e621d983c977c,0x00df77a9eccb66fb)},
- }}, {{
- {FIELD_LITERAL(0x002809e4bbf1814a,0x00b9e854f9fafb32,0x00d35e67c10f7a67,0x008f1bcb76e748cf,0x004224d9515687d2,0x005ba0b774e620c4,0x00b5e57db5d54119,0x00e15babe5683282)},
- {FIELD_LITERAL(0x00832d02369b482c,0x00cba52ff0d93450,0x003fa9c908d554db,0x008d1e357b54122f,0x00abd91c2dc950c6,0x007eff1df4c0ec69,0x003f6aeb13fb2d31,0x00002d6179fc5b2c)},
- {FIELD_LITERAL(0x0046c9eda81c9c89,0x00b60cb71c8f62fc,0x0022f5a683baa558,0x00f87319fccdf997,0x009ca09b51ce6a22,0x005b12baf4af7d77,0x008a46524a1e33e2,0x00035a77e988be0d)},
- }}, {{
- {FIELD_LITERAL(0x00a7efe46a7dbe2f,0x002f66fd55014fe7,0x006a428afa1ff026,0x0056caaa9604ab72,0x0033f3bcd7fac8ae,0x00ccb1aa01c86764,0x00158d1edf13bf40,0x009848ee76fcf3b4)},
- {FIELD_LITERAL(0x00a9e7730a819691,0x00d9cc73c4992b70,0x00e299bde067de5a,0x008c314eb705192a,0x00e7226f17e8a3cc,0x0029dfd956e65a47,0x0053a8e839073b12,0x006f942b2ab1597e)},
- {FIELD_LITERAL(0x001c3d780ecd5e39,0x0094f247fbdcc5fe,0x00d5c786fd527764,0x00b6f4da74f0db2a,0x0080f1f8badcd5fc,0x00f36a373ad2e23b,0x00f804f9f4343bf2,0x00d1af40ec623982)},
- }}, {{
- {FIELD_LITERAL(0x0082aeace5f1b144,0x00f68b3108cf4dd3,0x00634af01dde3020,0x000beab5df5c2355,0x00e8b790d1b49b0b,0x00e48d15854e36f4,0x0040ab2d95f3db9f,0x002711c4ed9e899a)},
- {FIELD_LITERAL(0x0039343746531ebe,0x00c8509d835d429d,0x00e79eceff6b0018,0x004abfd31e8efce5,0x007bbfaaa1e20210,0x00e3be89c193e179,0x001c420f4c31d585,0x00f414a315bef5ae)},
- {FIELD_LITERAL(0x007c296a24990df8,0x00d5d07525a75588,0x00dd8e113e94b7e7,0x007bbc58febe0cc8,0x0029f51af9bfcad3,0x007e9311ec7ab6f3,0x009a884de1676343,0x0050d5f2dce84be9)},
- }}, {{
- {FIELD_LITERAL(0x005fa020cca2450a,0x00491c29db6416d8,0x0037cefe3f9f9a85,0x003d405230647066,0x0049e835f0fdbe89,0x00feb78ac1a0815c,0x00828e4b32dc9724,0x00db84f2dc8d6fd4)},
- {FIELD_LITERAL(0x0098cddc8b39549a,0x006da37e3b05d22c,0x00ce633cfd4eb3cb,0x00fda288ef526acd,0x0025338878c5d30a,0x00f34438c4e5a1b4,0x00584efea7c310f1,0x0041a551f1b660ad)},
- {FIELD_LITERAL(0x00d7f7a8fbd6437a,0x0062872413bf3753,0x00ad4bbcb43c584b,0x007fe49be601d7e3,0x0077c659789babf4,0x00eb45fcb06a741b,0x005ce244913f9708,0x0088426401736326)},
- }}, {{
- {FIELD_LITERAL(0x007bf562ca768d7c,0x006c1f3a174e387c,0x00f024b447fee939,0x007e7af75f01143f,0x003adb70b4eed89d,0x00e43544021ad79a,0x0091f7f7042011f6,0x0093c1a1ee3a0ddc)},
- {FIELD_LITERAL(0x00a0b68ec1eb72d2,0x002c03235c0d45a0,0x00553627323fe8c5,0x006186e94b17af94,0x00a9906196e29f14,0x0025b3aee6567733,0x007e0dd840080517,0x0018eb5801a4ba93)},
- {FIELD_LITERAL(0x00d7fe7017bf6a40,0x006e3f0624be0c42,0x00ffbba205358245,0x00f9fc2cf8194239,0x008d93b37bf15b4e,0x006ddf2e38be8e95,0x002b6e79bf5fcff9,0x00ab355da425e2de)},
- }}, {{
- {FIELD_LITERAL(0x00938f97e20be973,0x0099141a36aaf306,0x0057b0ca29e545a1,0x0085db571f9fbc13,0x008b333c554b4693,0x0043ab6ef3e241cb,0x0054fb20aa1e5c70,0x00be0ff852760adf)},
- {FIELD_LITERAL(0x003973d8938971d6,0x002aca26fa80c1f5,0x00108af1faa6b513,0x00daae275d7924e6,0x0053634ced721308,0x00d2355fe0bbd443,0x00357612b2d22095,0x00f9bb9dd4136cf3)},
- {FIELD_LITERAL(0x002bff12cf5e03a5,0x001bdb1fa8a19cf8,0x00c91c6793f84d39,0x00f869f1b2eba9af,0x0059bc547dc3236b,0x00d91611d6d38689,0x00e062daaa2c0214,0x00ed3c047cc2bc82)},
- }}, {{
- {FIELD_LITERAL(0x000050d70c32b31a,0x001939d576d437b3,0x00d709e598bf9fe6,0x00a885b34bd2ee9e,0x00dd4b5c08ab1a50,0x0091bebd50b55639,0x00cf79ff64acdbc6,0x006067a39d826336)},
- {FIELD_LITERAL(0x0062dd0fb31be374,0x00fcc96b84c8e727,0x003f64f1375e6ae3,0x0057d9b6dd1af004,0x00d6a167b1103c7b,0x00dd28f3180fb537,0x004ff27ad7167128,0x008934c33461f2ac)},
- {FIELD_LITERAL(0x0065b472b7900043,0x00ba7efd2ff1064b,0x000b67d6c4c3020f,0x0012d28469f4e46d,0x0031c32939703ec7,0x00b49f0bce133066,0x00f7e10416181d47,0x005c90f51867eecc)},
- }}, {{
- {FIELD_LITERAL(0x0051207abd179101,0x00fc2a5c20d9c5da,0x00fb9d5f2701b6df,0x002dd040fdea82b8,0x00f163b0738442ff,0x00d9736bd68855b8,0x00e0d8e93005e61c,0x00df5a40b3988570)},
- {FIELD_LITERAL(0x0006918f5dfce6dc,0x00d4bf1c793c57fb,0x0069a3f649435364,0x00e89a50e5b0cd6e,0x00b9f6a237e973af,0x006d4ed8b104e41d,0x00498946a3924cd2,0x00c136ec5ac9d4f7)},
- {FIELD_LITERAL(0x0011a9c290ac5336,0x002b9a2d4a6a6533,0x009a8a68c445d937,0x00361b27b07e5e5c,0x003c043b1755b974,0x00b7eb66cf1155ee,0x0077af5909eefff2,0x0098f609877cc806)},
- }}, {{
- {FIELD_LITERAL(0x00ab13af436bf8f4,0x000bcf0a0dac8574,0x00d50c864f705045,0x00c40e611debc842,0x0085010489bd5caa,0x007c5050acec026f,0x00f67d943c8da6d1,0x00de1da0278074c6)},
- {FIELD_LITERAL(0x00b373076597455f,0x00e83f1af53ac0f5,0x0041f63c01dc6840,0x0097dea19b0c6f4b,0x007f9d63b4c1572c,0x00e692d492d0f5f0,0x00cbcb392e83b4ad,0x0069c0f39ed9b1a8)},
- {FIELD_LITERAL(0x00861030012707c9,0x009fbbdc7fd4aafb,0x008f591d6b554822,0x00df08a41ea18ade,0x009d7d83e642abea,0x0098c71bda3b78ff,0x0022c89e7021f005,0x0044d29a3fe1e3c4)},
- }}, {{
- {FIELD_LITERAL(0x00e748cd7b5c52f2,0x00ea9df883f89cc3,0x0018970df156b6c7,0x00c5a46c2a33a847,0x00cbde395e32aa09,0x0072474ebb423140,0x00fb00053086a23d,0x001dafcfe22d4e1f)},
- {FIELD_LITERAL(0x00c903ee6d825540,0x00add6c4cf98473e,0x007636efed4227f1,0x00905124ae55e772,0x00e6b38fab12ed53,0x0045e132b863fe55,0x003974662edb366a,0x00b1787052be8208)},
- {FIELD_LITERAL(0x00a614b00d775c7c,0x00d7c78941cc7754,0x00422dd68b5dabc4,0x00a6110f0167d28b,0x00685a309c252886,0x00b439ffd5143660,0x003656e29ee7396f,0x00c7c9b9ed5ad854)},
- }}, {{
- {FIELD_LITERAL(0x0040f7e7c5b37bf2,0x0064e4dc81181bba,0x00a8767ae2a366b6,0x001496b4f90546f2,0x002a28493f860441,0x0021f59513049a3a,0x00852d369a8b7ee3,0x00dd2e7d8b7d30a9)},
- {FIELD_LITERAL(0x00006e34a35d9fbc,0x00eee4e48b2f019a,0x006b344743003a5f,0x00541d514f04a7e3,0x00e81f9ee7647455,0x005e2b916c438f81,0x00116f8137b7eff0,0x009bd3decc7039d1)},
- {FIELD_LITERAL(0x0005d226f434110d,0x00af8288b8ef21d5,0x004a7a52ef181c8c,0x00be0b781b4b06de,0x00e6e3627ded07e1,0x00e43aa342272b8b,0x00e86ab424577d84,0x00fb292c566e35bb)},
- }}, {{
- {FIELD_LITERAL(0x00334f5303ea1222,0x00dfb3dbeb0a5d3e,0x002940d9592335c1,0x00706a7a63e8938a,0x005a533558bc4caf,0x00558e33192022a9,0x00970d9faf74c133,0x002979fcb63493ca)},
- {FIELD_LITERAL(0x00e38abece3c82ab,0x005a51f18a2c7a86,0x009dafa2e86d592e,0x00495a62eb688678,0x00b79df74c0eb212,0x0023e8cc78b75982,0x005998cb91075e13,0x00735aa9ba61bc76)},
- {FIELD_LITERAL(0x00d9f7a82ddbe628,0x00a1fc782889ae0f,0x0071ffda12d14b66,0x0037cf4eca7fb3d5,0x00c80bc242c58808,0x0075bf8c2d08c863,0x008d41f31afc52a7,0x00197962ecf38741)},
- }}, {{
- {FIELD_LITERAL(0x006e9f475cccf2ee,0x00454b9cd506430c,0x00224a4fb79ee479,0x0062e3347ef0b5e2,0x0034fd2a3512232a,0x00b8b3cb0f457046,0x00eb20165daa38ec,0x00128eebc2d9c0f7)},
- {FIELD_LITERAL(0x00bfc5fa1e4ea21f,0x00c21d7b6bb892e6,0x00cf043f3acf0291,0x00c13f2f849b3c90,0x00d1a97ebef10891,0x0061e130a445e7fe,0x0019513fdedbf22b,0x001d60c813bff841)},
- {FIELD_LITERAL(0x0019561c7fcf0213,0x00e3dca6843ebd77,0x0068ea95b9ca920e,0x009bdfb70f253595,0x00c68f59186aa02a,0x005aee1cca1c3039,0x00ab79a8a937a1ce,0x00b9a0e549959e6f)},
- }}, {{
- {FIELD_LITERAL(0x00c79e0b6d97dfbd,0x00917c71fd2bc6e8,0x00db7529ccfb63d8,0x00be5be957f17866,0x00a9e11fdc2cdac1,0x007b91a8e1f44443,0x00a3065e4057d80f,0x004825f5b8d5f6d4)},
- {FIELD_LITERAL(0x003e4964fa8a8fc8,0x00f6a1cdbcf41689,0x00943cb18fe7fda7,0x00606dafbf34440a,0x005d37a86399c789,0x00e79a2a69417403,0x00fe34f7e68b8866,0x0011f448ed2df10e)},
- {FIELD_LITERAL(0x00f1f57efcc1fcc4,0x00513679117de154,0x002e5b5b7c86d8c3,0x009f6486561f9cfb,0x00169e74b0170cf7,0x00900205af4af696,0x006acfddb77853f3,0x00df184c90f31068)},
- }}, {{
- {FIELD_LITERAL(0x00b37396c3320791,0x00fc7b67175c5783,0x00c36d2cd73ecc38,0x0080ebcc0b328fc5,0x0043a5b22b35d35d,0x00466c9f1713c9da,0x0026ad346dcaa8da,0x007c684e701183a6)},
- {FIELD_LITERAL(0x00fd579ffb691713,0x00b76af4f81c412d,0x00f239de96110f82,0x00e965fb437f0306,0x00ca7e9436900921,0x00e487f1325fa24a,0x00633907de476380,0x00721c62ac5b8ea0)},
- {FIELD_LITERAL(0x00c0d54e542eb4f9,0x004ed657171c8dcf,0x00b743a4f7c2a39b,0x00fd9f93ed6cc567,0x00307fae3113e58b,0x0058aa577c93c319,0x00d254556f35b346,0x00491aada2203f0d)},
- }}, {{
- {FIELD_LITERAL(0x00dff3103786ff34,0x000144553b1f20c3,0x0095613baeb930e4,0x00098058275ea5d4,0x007cd1402b046756,0x0074d74e4d58aee3,0x005f93fc343ff69b,0x00873df17296b3b0)},
- {FIELD_LITERAL(0x00c4a1fb48635413,0x00b5dd54423ad59f,0x009ff5d53fd24a88,0x003c98d267fc06a7,0x002db7cb20013641,0x00bd1d6716e191f2,0x006dbc8b29094241,0x0044bbf233dafa2c)},
- {FIELD_LITERAL(0x0055838d41f531e6,0x00bf6a2dd03c81b2,0x005827a061c4839e,0x0000de2cbb36aac3,0x002efa29d9717478,0x00f9e928cc8a77ba,0x00c134b458def9ef,0x00958a182223fc48)},
- }}, {{
- {FIELD_LITERAL(0x000a9ee23c06881f,0x002c727d3d871945,0x00f47d971512d24a,0x00671e816f9ef31a,0x00883af2cfaad673,0x00601f98583d6c9a,0x00b435f5adc79655,0x00ad87b71c04bff2)},
- {FIELD_LITERAL(0x007860d99db787cf,0x00fda8983018f4a8,0x008c8866bac4743c,0x00ef471f84c82a3f,0x00abea5976d3b8e7,0x00714882896cd015,0x00b49fae584ddac5,0x008e33a1a0b69c81)},
- {FIELD_LITERAL(0x007b6ee2c9e8a9ec,0x002455dbbd89d622,0x006490cf4eaab038,0x00d925f6c3081561,0x00153b3047de7382,0x003b421f8bdceb6f,0x00761a4a5049da78,0x00980348c5202433)},
- }}, {{
- {FIELD_LITERAL(0x007f8a43da97dd5c,0x00058539c800fc7b,0x0040f3cf5a28414a,0x00d68dd0d95283d6,0x004adce9da90146e,0x00befa41c7d4f908,0x007603bc2e3c3060,0x00bdf360ab3545db)},
- {FIELD_LITERAL(0x00eebfd4e2312cc3,0x00474b2564e4fc8c,0x003303ef14b1da9b,0x003c93e0e66beb1d,0x0013619b0566925a,0x008817c24d901bf3,0x00b62bd8898d218b,0x0075a7716f1e88a2)},
- {FIELD_LITERAL(0x0009218da1e6890f,0x0026907f5fd02575,0x004dabed5f19d605,0x003abf181870249d,0x00b52fd048cc92c4,0x00b6dd51e415a5c5,0x00d9eb82bd2b4014,0x002c865a43b46b43)},
- }}, {{
- {FIELD_LITERAL(0x0070047189452f4c,0x00f7ad12e1ce78d5,0x00af1ba51ec44a8b,0x005f39f63e667cd6,0x00058eac4648425e,0x00d7fdab42bea03b,0x0028576a5688de15,0x00af973209e77c10)},
- {FIELD_LITERAL(0x00c338b915d8fef0,0x00a893292045c39a,0x0028ab4f2eba6887,0x0060743cb519fd61,0x0006213964093ac0,0x007c0b7a43f6266d,0x008e3557c4fa5bda,0x002da976de7b8d9d)},
- {FIELD_LITERAL(0x0048729f8a8b6dcd,0x00fe23b85cc4d323,0x00e7384d16e4db0e,0x004a423970678942,0x00ec0b763345d4ba,0x00c477b9f99ed721,0x00c29dad3777b230,0x001c517b466f7df6)},
- }}, {{
- {FIELD_LITERAL(0x006366c380f7b574,0x001c7d1f09ff0438,0x003e20a7301f5b22,0x00d3efb1916d28f6,0x0049f4f81060ce83,0x00c69d91ea43ced1,0x002b6f3e5cd269ed,0x005b0fb22ce9ec65)},
- {FIELD_LITERAL(0x00aa2261022d883f,0x00ebcca4548010ac,0x002528512e28a437,0x0070ca7676b66082,0x0084bda170f7c6d3,0x00581b4747c9b8bb,0x005c96a01061c7e2,0x00fb7c4a362b5273)},
- {FIELD_LITERAL(0x00c30020eb512d02,0x0060f288283a4d26,0x00b7ed13becde260,0x0075ebb74220f6e9,0x00701079fcfe8a1f,0x001c28fcdff58938,0x002e4544b8f4df6b,0x0060c5bc4f1a7d73)},
- }}, {{
- {FIELD_LITERAL(0x00ae307cf069f701,0x005859f222dd618b,0x00212d6c46ec0b0d,0x00a0fe4642afb62d,0x00420d8e4a0a8903,0x00a80ff639bdf7b0,0x0019bee1490b5d8e,0x007439e4b9c27a86)},
- {FIELD_LITERAL(0x00a94700032a093f,0x0076e96c225216e7,0x00a63a4316e45f91,0x007d8bbb4645d3b2,0x00340a6ff22793eb,0x006f935d4572aeb7,0x00b1fb69f00afa28,0x009e8f3423161ed3)},
- {FIELD_LITERAL(0x009ef49c6b5ced17,0x00a555e6269e9f0a,0x007e6f1d79ec73b5,0x009ac78695a32ac4,0x0001d77fbbcd5682,0x008cea1fee0aaeed,0x00f42bea82a53462,0x002e46ab96cafcc9)},
- }}, {{
- {FIELD_LITERAL(0x0051cfcc5885377a,0x00dce566cb1803ca,0x00430c7643f2c7d4,0x00dce1a1337bdcc0,0x0010d5bd7283c128,0x003b1b547f9b46fe,0x000f245e37e770ab,0x007b72511f022b37)},
- {FIELD_LITERAL(0x0060db815bc4786c,0x006fab25beedc434,0x00c610d06084797c,0x000c48f08537bec0,0x0031aba51c5b93da,0x007968fa6e01f347,0x0030070da52840c6,0x00c043c225a4837f)},
- {FIELD_LITERAL(0x001bcfd00649ee93,0x006dceb47e2a0fd5,0x00f2cebda0cf8fd0,0x00b6b9d9d1fbdec3,0x00815262e6490611,0x00ef7f5ce3176760,0x00e49cd0c998d58b,0x005fc6cc269ba57c)},
- }}, {{
- {FIELD_LITERAL(0x008940211aa0d633,0x00addae28136571d,0x00d68fdbba20d673,0x003bc6129bc9e21a,0x000346cf184ebe9a,0x0068774d741ebc7f,0x0019d5e9e6966557,0x0003cbd7f981b651)},
- {FIELD_LITERAL(0x004a2902926f8d3f,0x00ad79b42637ab75,0x0088f60b90f2d4e8,0x0030f54ef0e398c4,0x00021dc9bf99681e,0x007ebf66fde74ee3,0x004ade654386e9a4,0x00e7485066be4c27)},
- {FIELD_LITERAL(0x00445f1263983be0,0x004cf371dda45e6a,0x00744a89d5a310e7,0x001f20ce4f904833,0x00e746edebe66e29,0x000912ab1f6c153d,0x00f61d77d9b2444c,0x0001499cd6647610)},
+ {FIELD_LITERAL(0x00cc3b062366f4ccULL, 0x003d6e34e314aa3cULL,
+ 0x00d51c0a7521774dULL, 0x0094e060eec6ab8bULL,
+ 0x00d21291b4d80082ULL, 0x00befed12b55ef1eULL,
+ 0x00c3dd2df5c94518ULL, 0x00e0a7b112b8d4e6ULL)},
+ {FIELD_LITERAL(0x0019eb5608d8723aULL, 0x00d1bab52fb3aedbULL,
+ 0x00270a7311ebc90cULL, 0x0037c12b91be7f13ULL,
+ 0x005be16cd8b5c704ULL, 0x003e181acda888e1ULL,
+ 0x00bc1f00fc3fc6d0ULL, 0x00d3839bfa319e20ULL)},
+ {FIELD_LITERAL(0x003caeb88611909fULL, 0x00ea8b378c4df3d4ULL,
+ 0x00b3295b95a5a19aULL, 0x00a65f97514bdfb5ULL,
+ 0x00b39efba743cab1ULL, 0x0016ba98b862fd2dULL,
+ 0x0001508812ee71d7ULL, 0x000a75740eea114aULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00ebcf0eb649f823ULL, 0x00166d332e98ea03ULL,
+ 0x0059ddf64f5cd5f6ULL, 0x0047763123d9471bULL,
+ 0x00a64065c53ef62fULL, 0x00978e44c480153dULL,
+ 0x000b5b2a0265f194ULL, 0x0046a24b9f32965aULL)},
+ {FIELD_LITERAL(0x00b9eef787034df0ULL, 0x0020bc24de3390cdULL,
+ 0x000022160bae99bbULL, 0x00ae66e886e97946ULL,
+ 0x0048d4bbe02cbb8bULL, 0x0072ba97b34e38d4ULL,
+ 0x00eae7ec8f03e85aULL, 0x005ba92ecf808b2cULL)},
+ {FIELD_LITERAL(0x00c9cfbbe74258fdULL, 0x00843a979ea9eaa7ULL,
+ 0x000cbb4371cfbe90ULL, 0x0059bac8f7f0a628ULL,
+ 0x004b3dff882ff530ULL, 0x0011869df4d90733ULL,
+ 0x00595aa71f4abfc2ULL, 0x0070e2d38990c2e6ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00de2010c0a01733ULL, 0x00c739a612e24297ULL,
+ 0x00a7212643141d7cULL, 0x00f88444f6b67c11ULL,
+ 0x00484b7b16ec28f2ULL, 0x009c1b8856af9c68ULL,
+ 0x00ff4669591fe9d6ULL, 0x0054974be08a32c8ULL)},
+ {FIELD_LITERAL(0x0010de3fd682ceedULL, 0x008c07642d83ca4eULL,
+ 0x0013bb064e00a1ccULL, 0x009411ae27870e11ULL,
+ 0x00ea8e5b4d531223ULL, 0x0032fe7d2aaece2eULL,
+ 0x00d989e243e7bb41ULL, 0x000fe79a508e9b8bULL)},
+ {FIELD_LITERAL(0x005e0426b9bfc5b1ULL, 0x0041a5b1d29ee4faULL,
+ 0x0015b0def7774391ULL, 0x00bc164f1f51af01ULL,
+ 0x00d543b0942797b9ULL, 0x003c129b6398099cULL,
+ 0x002b114c6e5adf18ULL, 0x00b4e630e4018a7bULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00d490afc95f8420ULL, 0x00b096bf50c1d9b9ULL,
+ 0x00799fd707679866ULL, 0x007c74d9334afbeaULL,
+ 0x00efaa8be80ff4edULL, 0x0075c4943bb81694ULL,
+ 0x00c21c2fca161f36ULL, 0x00e77035d492bfeeULL)},
+ {FIELD_LITERAL(0x006658a190dd6661ULL, 0x00e0e9bab38609a6ULL,
+ 0x0028895c802237edULL, 0x006a0229c494f587ULL,
+ 0x002dcde96c9916b7ULL, 0x00d158822de16218ULL,
+ 0x00173b917a06856fULL, 0x00ca78a79ae07326ULL)},
+ {FIELD_LITERAL(0x00e35bfc79caced4ULL, 0x0087238a3e1fe3bbULL,
+ 0x00bcbf0ff4ceff5bULL, 0x00a19c1c94099b91ULL,
+ 0x0071e102b49db976ULL, 0x0059e3d004eada1eULL,
+ 0x008da78afa58a47eULL, 0x00579c8ebf269187ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00a16c2905eee75fULL, 0x009d4bcaea2c7e1dULL,
+ 0x00d3bd79bfad19dfULL, 0x0050da745193342cULL,
+ 0x006abdb8f6b29ab1ULL, 0x00a24fe0a4fef7efULL,
+ 0x0063730da1057dfbULL, 0x00a08c312c8eb108ULL)},
+ {FIELD_LITERAL(0x00b583be005375beULL, 0x00a40c8f8a4e3df4ULL,
+ 0x003fac4a8f5bdbf7ULL, 0x00d4481d872cd718ULL,
+ 0x004dc8749cdbaefeULL, 0x00cce740d5e5c975ULL,
+ 0x000b1c1f4241fd21ULL, 0x00a76de1b4e1cd07ULL)},
+ {FIELD_LITERAL(0x007a076500d30b62ULL, 0x000a6e117b7f090fULL,
+ 0x00c8712ae7eebd9aULL, 0x000fbd6c1d5f6ff7ULL,
+ 0x003a7977246ebf11ULL, 0x00166ed969c6600eULL,
+ 0x00aa42e469c98becULL, 0x00dc58f307cf0666ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x004b491f65a9a28bULL, 0x006a10309e8a55b7ULL,
+ 0x00b67210185187efULL, 0x00cf6497b12d9b8fULL,
+ 0x0085778c56e2b1baULL, 0x0015b4c07a814d85ULL,
+ 0x00686479e62da561ULL, 0x008de5d88f114916ULL)},
+ {FIELD_LITERAL(0x00e37c88d6bba7b1ULL, 0x003e4577e1b8d433ULL,
+ 0x0050d8ea5f510ec0ULL, 0x0042fc9f2da9ef59ULL,
+ 0x003bd074c1141420ULL, 0x00561b8b7b68774eULL,
+ 0x00232e5e5d1013a3ULL, 0x006b7f2cb3d7e73fULL)},
+ {FIELD_LITERAL(0x004bdd0f0b41e6a0ULL, 0x001773057c405d24ULL,
+ 0x006029f99915bd97ULL, 0x006a5ba70a17fe2fULL,
+ 0x0046111977df7e08ULL, 0x004d8124c89fb6b7ULL,
+ 0x00580983b2bb2724ULL, 0x00207bf330d6f3feULL)},
+ }}, {{
+ {FIELD_LITERAL(0x007efdc93972a48bULL, 0x002f5e50e78d5feeULL,
+ 0x0080dc11d61c7fe5ULL, 0x0065aa598707245bULL,
+ 0x009abba2300641beULL, 0x000c68787656543aULL,
+ 0x00ffe0fef2dc0a17ULL, 0x00007ffbd6cb4f3aULL)},
+ {FIELD_LITERAL(0x0036012f2b836efcULL, 0x00458c126d6b5fbcULL,
+ 0x00a34436d719ad1eULL, 0x0097be6167117deaULL,
+ 0x0009c219c879cff3ULL, 0x0065564493e60755ULL,
+ 0x00993ac94a8cdec0ULL, 0x002d4885a4d0dbafULL)},
+ {FIELD_LITERAL(0x00598b60b4c068baULL, 0x00c547a0be7f1afdULL,
+ 0x009582164acf12afULL, 0x00af4acac4fbbe40ULL,
+ 0x005f6ca7c539121aULL, 0x003b6e752ebf9d66ULL,
+ 0x00f08a30d5cac5d4ULL, 0x00e399bb5f97c5a9ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x007445a0409c0a66ULL, 0x00a65c369f3829c0ULL,
+ 0x0031d248a4f74826ULL, 0x006817f34defbe8eULL,
+ 0x00649741d95ebf2eULL, 0x00d46466ab16b397ULL,
+ 0x00fdc35703bee414ULL, 0x00343b43334525f8ULL)},
+ {FIELD_LITERAL(0x001796bea93f6401ULL, 0x00090c5a42e85269ULL,
+ 0x00672412ba1252edULL, 0x001201d47b6de7deULL,
+ 0x006877bccfe66497ULL, 0x00b554fd97a4c161ULL,
+ 0x009753f42dbac3cfULL, 0x00e983e3e378270aULL)},
+ {FIELD_LITERAL(0x00ac3eff18849872ULL, 0x00f0eea3bff05690ULL,
+ 0x00a6d72c21dd505dULL, 0x001b832642424169ULL,
+ 0x00a6813017b540e5ULL, 0x00a744bd71b385cdULL,
+ 0x0022a7d089130a7bULL, 0x004edeec9a133486ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00b2d6729196e8a9ULL, 0x0088a9bb2031cef4ULL,
+ 0x00579e7787dc1567ULL, 0x0030f49feb059190ULL,
+ 0x00a0b1d69c7f7d8fULL, 0x0040bdcc6d9d806fULL,
+ 0x00d76c4037edd095ULL, 0x00bbf24376415dd7ULL)},
+ {FIELD_LITERAL(0x00240465ff5a7197ULL, 0x00bb97e76caf27d0ULL,
+ 0x004b4edbf8116d39ULL, 0x001d8586f708cbaaULL,
+ 0x000f8ee8ff8e4a50ULL, 0x00dde5a1945dd622ULL,
+ 0x00e6fc1c0957e07cULL, 0x0041c9cdabfd88a0ULL)},
+ {FIELD_LITERAL(0x005344b0bf5b548cULL, 0x002957d0b705cc99ULL,
+ 0x00f586a70390553dULL, 0x0075b3229f583cc3ULL,
+ 0x00a1aa78227490e4ULL, 0x001bf09cf7957717ULL,
+ 0x00cf6bf344325f52ULL, 0x0065bd1c23ca3ecfULL)},
+ }}, {{
+ {FIELD_LITERAL(0x009bff3b3239363cULL, 0x00e17368796ef7c0ULL,
+ 0x00528b0fe0971f3aULL, 0x0008014fc8d4a095ULL,
+ 0x00d09f2e8a521ec4ULL, 0x006713ab5dde5987ULL,
+ 0x0003015758e0dbb1ULL, 0x00215999f1ba212dULL)},
+ {FIELD_LITERAL(0x002c88e93527da0eULL, 0x0077c78f3456aad5ULL,
+ 0x0071087a0a389d1cULL, 0x00934dac1fb96dbdULL,
+ 0x008470e801162697ULL, 0x005bc2196cd4ad49ULL,
+ 0x00e535601d5087c3ULL, 0x00769888700f497fULL)},
+ {FIELD_LITERAL(0x00da7a4b557298adULL, 0x0019d2589ea5df76ULL,
+ 0x00ef3e38be0c6497ULL, 0x00a9644e1312609aULL,
+ 0x004592f61b2558daULL, 0x0082c1df510d7e46ULL,
+ 0x0042809a535c0023ULL, 0x00215bcb5afd7757ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x002b9df55a1a4213ULL, 0x00dcfc3b464a26beULL,
+ 0x00c4f9e07a8144d5ULL, 0x00c8e0617a92b602ULL,
+ 0x008e3c93accafae0ULL, 0x00bf1bcb95b2ca60ULL,
+ 0x004ce2426a613bf3ULL, 0x00266cac58e40921ULL)},
+ {FIELD_LITERAL(0x008456d5db76e8f0ULL, 0x0032ca9cab2ce163ULL,
+ 0x0059f2b8bf91abcfULL, 0x0063c2a021712788ULL,
+ 0x00f86155af22f72dULL, 0x00db98b2a6c005a0ULL,
+ 0x00ac6e416a693ac4ULL, 0x007a93572af53226ULL)},
+ {FIELD_LITERAL(0x0087767520f0de22ULL, 0x0091f64012279fb5ULL,
+ 0x001050f1f0644999ULL, 0x004f097a2477ad3cULL,
+ 0x006b37913a9947bdULL, 0x001a3d78645af241ULL,
+ 0x0057832bbb3008a7ULL, 0x002c1d902b80dc20ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x001a6002bf178877ULL, 0x009bce168aa5af50ULL,
+ 0x005fc318ff04a7f5ULL, 0x0052818f55c36461ULL,
+ 0x008768f5d4b24afbULL, 0x0037ffbae7b69c85ULL,
+ 0x0018195a4b61edc0ULL, 0x001e12ea088434b2ULL)},
+ {FIELD_LITERAL(0x0047d3f804e7ab07ULL, 0x00a809ab5f905260ULL,
+ 0x00b3ffc7cdaf306dULL, 0x00746e8ec2d6e509ULL,
+ 0x00d0dade8887a645ULL, 0x00acceeebde0dd37ULL,
+ 0x009bc2579054686bULL, 0x0023804f97f1c2bfULL)},
+ {FIELD_LITERAL(0x0043e2e2e50b80d7ULL, 0x00143aafe4427e0fULL,
+ 0x005594aaecab855bULL, 0x008b12ccaaecbc01ULL,
+ 0x002deeb091082bc3ULL, 0x009cca4be2ae7514ULL,
+ 0x00142b96e696d047ULL, 0x00ad2a2b1c05256aULL)},
+ }}, {{
+ {FIELD_LITERAL(0x003914f2f144b78bULL, 0x007a95dd8bee6f68ULL,
+ 0x00c7f4384d61c8e6ULL, 0x004e51eb60f1bdb2ULL,
+ 0x00f64be7aa4621d8ULL, 0x006797bfec2f0ac0ULL,
+ 0x007d17aab3c75900ULL, 0x001893e73cac8bc5ULL)},
+ {FIELD_LITERAL(0x00140360b768665bULL, 0x00b68aca4967f977ULL,
+ 0x0001089b66195ae4ULL, 0x00fe71122185e725ULL,
+ 0x000bca2618d49637ULL, 0x00a54f0557d7e98aULL,
+ 0x00cdcd2f91d6f417ULL, 0x00ab8c13741fd793ULL)},
+ {FIELD_LITERAL(0x00725ee6b1e549e0ULL, 0x007124a0769777faULL,
+ 0x000b68fdad07ae42ULL, 0x0085b909cd4952dfULL,
+ 0x0092d2e3c81606f4ULL, 0x009f22f6cac099a0ULL,
+ 0x00f59da57f2799a8ULL, 0x00f06c090122f777ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00ce0bed0a3532bcULL, 0x001a5048a22df16bULL,
+ 0x00e31db4cbad8bf1ULL, 0x00e89292120cf00eULL,
+ 0x007d1dd1a9b00034ULL, 0x00e2a9041ff8f680ULL,
+ 0x006a4c837ae596e7ULL, 0x00713af1068070b3ULL)},
+ {FIELD_LITERAL(0x00c4fe64ce66d04bULL, 0x00b095d52e09b3d7ULL,
+ 0x00758bbecb1a3a8eULL, 0x00f35cce8d0650c0ULL,
+ 0x002b878aa5984473ULL, 0x0062e0a3b7544ddcULL,
+ 0x00b25b290ed116feULL, 0x007b0f6abe0bebf2ULL)},
+ {FIELD_LITERAL(0x0081d4e3addae0a8ULL, 0x003410c836c7ffccULL,
+ 0x00c8129ad89e4314ULL, 0x000e3d5a23922dcdULL,
+ 0x00d91e46f29c31f3ULL, 0x006c728cde8c5947ULL,
+ 0x002bc655ba2566c0ULL, 0x002ca94721533108ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x0051e4b3f764d8a9ULL, 0x0019792d46e904a0ULL,
+ 0x00853bc13dbc8227ULL, 0x000840208179f12dULL,
+ 0x0068243474879235ULL, 0x0013856fbfe374d0ULL,
+ 0x00bda12fe8676424ULL, 0x00bbb43635926eb2ULL)},
+ {FIELD_LITERAL(0x0012cdc880a93982ULL, 0x003c495b21cd1b58ULL,
+ 0x00b7e5c93f22a26eULL, 0x0044aa82dfb99458ULL,
+ 0x009ba092cdffe9c0ULL, 0x00a14b3ab2083b73ULL,
+ 0x000271c2f70e1c4bULL, 0x00eea9cac0f66eb8ULL)},
+ {FIELD_LITERAL(0x001a1847c4ac5480ULL, 0x00b1b412935bb03aULL,
+ 0x00f74285983bf2b2ULL, 0x00624138b5b5d0f1ULL,
+ 0x008820c0b03d38bfULL, 0x00b94e50a18c1572ULL,
+ 0x0060f6934841798fULL, 0x00c52f5d66d6ebe2ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00da23d59f9bcea6ULL, 0x00e0f27007a06a4bULL,
+ 0x00128b5b43a6758cULL, 0x000cf50190fa8b56ULL,
+ 0x00fc877aba2b2d72ULL, 0x00623bef52edf53fULL,
+ 0x00e6af6b819669e2ULL, 0x00e314dc34fcaa4fULL)},
+ {FIELD_LITERAL(0x0066e5eddd164d1eULL, 0x00418a7c6fe28238ULL,
+ 0x0002e2f37e962c25ULL, 0x00f01f56b5975306ULL,
+ 0x0048842fa503875cULL, 0x0057b0e968078143ULL,
+ 0x00ff683024f3d134ULL, 0x0082ae28fcad12e4ULL)},
+ {FIELD_LITERAL(0x0011ddfd21260e42ULL, 0x00d05b0319a76892ULL,
+ 0x00183ea4368e9b8fULL, 0x00b0815662affc96ULL,
+ 0x00b466a5e7ce7c88ULL, 0x00db93b07506e6eeULL,
+ 0x0033885f82f62401ULL, 0x0086f9090ec9b419ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00d95d1c5fcb435aULL, 0x0016d1ed6b5086f9ULL,
+ 0x00792aa0b7e54d71ULL, 0x0067b65715f1925dULL,
+ 0x00a219755ec6176bULL, 0x00bc3f026b12c28fULL,
+ 0x00700c897ffeb93eULL, 0x0089b83f6ec50b46ULL)},
+ {FIELD_LITERAL(0x003c97e6384da36eULL, 0x00423d53eac81a09ULL,
+ 0x00b70d68f3cdce35ULL, 0x00ee7959b354b92cULL,
+ 0x00f4e9718819c8caULL, 0x009349f12acbffe9ULL,
+ 0x005aee7b62cb7da6ULL, 0x00d97764154ffc86ULL)},
+ {FIELD_LITERAL(0x00526324babb46dcULL, 0x002ee99b38d7bf9eULL,
+ 0x007ea51794706ef4ULL, 0x00abeb04da6e3c39ULL,
+ 0x006b457c1d281060ULL, 0x00fe243e9a66c793ULL,
+ 0x00378de0fb6c6ee4ULL, 0x003e4194b9c3cb93ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00fed3cd80ca2292ULL, 0x0015b043a73ca613ULL,
+ 0x000a9fd7bf9be227ULL, 0x003b5e03de2db983ULL,
+ 0x005af72d46904ef7ULL, 0x00c0f1b5c49faa99ULL,
+ 0x00dc86fc3bd305e1ULL, 0x00c92f08c1cb1797ULL)},
+ {FIELD_LITERAL(0x0079680ce111ed3bULL, 0x001a1ed82806122cULL,
+ 0x000c2e7466d15df3ULL, 0x002c407f6f7150fdULL,
+ 0x00c5e7c96b1b0ce3ULL, 0x009aa44626863ff9ULL,
+ 0x00887b8b5b80be42ULL, 0x00b6023cec964825ULL)},
+ {FIELD_LITERAL(0x00e4a8e1048970c8ULL, 0x0062887b7830a302ULL,
+ 0x00bcf1c8cd81402bULL, 0x0056dbb81a68f5beULL,
+ 0x0014eced83f12452ULL, 0x00139e1a510150dfULL,
+ 0x00bb81140a82d1a3ULL, 0x000febcc1aaf1aa7ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00a7527958238159ULL, 0x0013ec9537a84cd6ULL,
+ 0x001d7fee7d562525ULL, 0x00b9eefa6191d5e5ULL,
+ 0x00dbc97db70bcb8aULL, 0x00481affc7a4d395ULL,
+ 0x006f73d3e70c31bbULL, 0x00183f324ed96a61ULL)},
+ {FIELD_LITERAL(0x0039dd7ce7fc6860ULL, 0x00d64f6425653da1ULL,
+ 0x003e037c7f57d0afULL, 0x0063477a06e2bcf2ULL,
+ 0x001727dbb7ac67e6ULL, 0x0049589f5efafe2eULL,
+ 0x00fc0fef2e813d54ULL, 0x008baa5d087fb50dULL)},
+ {FIELD_LITERAL(0x0024fb59d9b457c7ULL, 0x00a7d4e060223e4cULL,
+ 0x00c118d1b555fd80ULL, 0x0082e216c732f22aULL,
+ 0x00cd2a2993089504ULL, 0x003638e836a3e13dULL,
+ 0x000d855ee89b4729ULL, 0x008ec5b7d4810c91ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x001bf51f7d65cdfdULL, 0x00d14cdafa16a97dULL,
+ 0x002c38e60fcd10e7ULL, 0x00a27446e393efbdULL,
+ 0x000b5d8946a71fddULL, 0x0063df2cde128f2fULL,
+ 0x006c8679569b1888ULL, 0x0059ffc4925d732dULL)},
+ {FIELD_LITERAL(0x00ece96f95f2b66fULL, 0x00ece7952813a27bULL,
+ 0x0026fc36592e489eULL, 0x007157d1a2de0f66ULL,
+ 0x00759dc111d86ddfULL, 0x0012881e5780bb0fULL,
+ 0x00c8ccc83ad29496ULL, 0x0012b9bd1929eb71ULL)},
+ {FIELD_LITERAL(0x000fa15a20da5df0ULL, 0x00349ddb1a46cd31ULL,
+ 0x002c512ad1d8e726ULL, 0x00047611f669318dULL,
+ 0x009e68fba591e17eULL, 0x004320dffa803906ULL,
+ 0x00a640874951a3d3ULL, 0x00b6353478baa24fULL)},
+ }}, {{
+ {FIELD_LITERAL(0x009696510000d333ULL, 0x00ec2f788bc04826ULL,
+ 0x000e4d02b1f67ba5ULL, 0x00659aa8dace08b6ULL,
+ 0x00d7a38a3a3ae533ULL, 0x008856defa8c746bULL,
+ 0x004d7a4402d3da1aULL, 0x00ea82e06229260fULL)},
+ {FIELD_LITERAL(0x006a15bb20f75c0cULL, 0x0079a144027a5d0cULL,
+ 0x00d19116ce0b4d70ULL, 0x0059b83bcb0b268eULL,
+ 0x005f58f63f16c127ULL, 0x0079958318ee2c37ULL,
+ 0x00defbb063d07f82ULL, 0x00f1f0b931d2d446ULL)},
+ {FIELD_LITERAL(0x00cb5e4c3c35d422ULL, 0x008df885ca43577fULL,
+ 0x00fa50b16ca3e471ULL, 0x005a0e58e17488c8ULL,
+ 0x00b2ceccd6d34d19ULL, 0x00f01d5d235e36e9ULL,
+ 0x00db2e7e4be6ca44ULL, 0x00260ab77f35fccdULL)},
+ }}, {{
+ {FIELD_LITERAL(0x006f6fd9baac61d5ULL, 0x002a7710a020a895ULL,
+ 0x009de0db7fc03d4dULL, 0x00cdedcb1875f40bULL,
+ 0x00050caf9b6b1e22ULL, 0x005e3a6654456ab0ULL,
+ 0x00775fdf8c4423d4ULL, 0x0028701ea5738b5dULL)},
+ {FIELD_LITERAL(0x009ffd90abfeae96ULL, 0x00cba3c2b624a516ULL,
+ 0x005ef08bcee46c91ULL, 0x00e6fde30afb6185ULL,
+ 0x00f0b4db4f818ce4ULL, 0x006c54f45d2127f5ULL,
+ 0x00040125035854c7ULL, 0x00372658a3287e13ULL)},
+ {FIELD_LITERAL(0x00d7070fb1beb2abULL, 0x0078fc845a93896bULL,
+ 0x006894a4b2f224a6ULL, 0x005bdd8192b9dbdeULL,
+ 0x00b38839874b3a9eULL, 0x00f93618b04b7a57ULL,
+ 0x003e3ec75fd2c67eULL, 0x00bf5e6bfc29494aULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00f19224ebba2aa5ULL, 0x0074f89d358e694dULL,
+ 0x00eea486597135adULL, 0x0081579a4555c7e1ULL,
+ 0x0010b9b872930a9dULL, 0x00f002e87a30ecc0ULL,
+ 0x009b9d66b6de56e2ULL, 0x00a3c4f45e8004ebULL)},
+ {FIELD_LITERAL(0x0045e8dda9400888ULL, 0x002ff12e5fc05db7ULL,
+ 0x00a7098d54afe69cULL, 0x00cdbe846a500585ULL,
+ 0x00879c1593ca1882ULL, 0x003f7a7fea76c8b0ULL,
+ 0x002cd73dd0c8e0a1ULL, 0x00645d6ce96f51feULL)},
+ {FIELD_LITERAL(0x002b7e83e123d6d6ULL, 0x00398346f7419c80ULL,
+ 0x0042922e55940163ULL, 0x005e7fc5601886a3ULL,
+ 0x00e88f2cee1d3103ULL, 0x00e7fab135f2e377ULL,
+ 0x00b059984dbf0dedULL, 0x0009ce080faa5bb8ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x0085e78af7758979ULL, 0x00275a4ee1631a3aULL,
+ 0x00d26bc0ed78b683ULL, 0x004f8355ea21064fULL,
+ 0x00d618e1a32696e5ULL, 0x008d8d7b150e5680ULL,
+ 0x00a74cd854b278d2ULL, 0x001dd62702203ea0ULL)},
+ {FIELD_LITERAL(0x00f89335c2a59286ULL, 0x00a0f5c905d55141ULL,
+ 0x00b41fb836ee9382ULL, 0x00e235d51730ca43ULL,
+ 0x00a5cb37b5c0a69aULL, 0x009b966ffe136c45ULL,
+ 0x00cb2ea10bf80ed1ULL, 0x00fb2b370b40dc35ULL)},
+ {FIELD_LITERAL(0x00d687d16d4ee8baULL, 0x0071520bdd069dffULL,
+ 0x00de85c60d32355dULL, 0x0087d2e3565102f4ULL,
+ 0x00cde391b8dfc9aaULL, 0x00e18d69efdfefe5ULL,
+ 0x004a9d0591954e91ULL, 0x00fa36dd8b50eee5ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x002e788749a865f7ULL, 0x006e4dc3116861eaULL,
+ 0x009f1428c37276e6ULL, 0x00e7d2e0fc1e1226ULL,
+ 0x003aeebc6b6c45f6ULL, 0x0071a8073bf500c9ULL,
+ 0x004b22ad986b530cULL, 0x00f439e63c0d79d4ULL)},
+ {FIELD_LITERAL(0x006bc3d53011f470ULL, 0x00032d6e692b83e8ULL,
+ 0x00059722f497cd0bULL, 0x0009b4e6f0c497ccULL,
+ 0x0058a804b7cce6c0ULL, 0x002b71d3302bbd5dULL,
+ 0x00e2f82a36765fceULL, 0x008dded99524c703ULL)},
+ {FIELD_LITERAL(0x004d058953747d64ULL, 0x00701940fe79aa6fULL,
+ 0x00a620ac71c760bfULL, 0x009532b611158b75ULL,
+ 0x00547ed7f466f300ULL, 0x003cb5ab53a8401aULL,
+ 0x00c7763168ce3120ULL, 0x007e48e33e4b9ab2ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x001b2fc57bf3c738ULL, 0x006a3f918993fb80ULL,
+ 0x0026f7a14fdec288ULL, 0x0075a2cdccef08dbULL,
+ 0x00d3ecbc9eecdbf1ULL, 0x0048c40f06e5bf7fULL,
+ 0x00d63e423009896bULL, 0x000598bc99c056a8ULL)},
+ {FIELD_LITERAL(0x002f194eaafa46dcULL, 0x008e38f57fe87613ULL,
+ 0x00dc8e5ae25f4ab2ULL, 0x000a17809575e6bdULL,
+ 0x00d3ec7923ba366aULL, 0x003a7e72e0ad75e3ULL,
+ 0x0010024b88436e0aULL, 0x00ed3c5444b64051ULL)},
+ {FIELD_LITERAL(0x00831fc1340af342ULL, 0x00c9645669466d35ULL,
+ 0x007692b4cc5a080fULL, 0x009fd4a47ac9259fULL,
+ 0x001eeddf7d45928bULL, 0x003c0446fc45f28bULL,
+ 0x002c0713aa3e2507ULL, 0x0095706935f0f41eULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00766ae4190ec6d8ULL, 0x0065768cabc71380ULL,
+ 0x00b902598416cdc2ULL, 0x00380021ad38df52ULL,
+ 0x008f0b89d6551134ULL, 0x004254d4cc62c5a5ULL,
+ 0x000d79f4484b9b94ULL, 0x00b516732ae3c50eULL)},
+ {FIELD_LITERAL(0x001fb73475c45509ULL, 0x00d2b2e5ea43345aULL,
+ 0x00cb3c3842077bd1ULL, 0x0029f90ad820946eULL,
+ 0x007c11b2380778aaULL, 0x009e54ece62c1704ULL,
+ 0x004bc60c41ca01c3ULL, 0x004525679a5a0b03ULL)},
+ {FIELD_LITERAL(0x00c64fbddbed87b3ULL, 0x0040601d11731faaULL,
+ 0x009c22475b6f9d67ULL, 0x0024b79dae875f15ULL,
+ 0x00616fed3f02c3b0ULL, 0x0000cf39f6af2d3bULL,
+ 0x00c46bac0aa9a688ULL, 0x00ab23e2800da204ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x000b3a37617632b0ULL, 0x00597199fe1cfb6cULL,
+ 0x0042a7ccdfeafdd6ULL, 0x004cc9f15ebcea17ULL,
+ 0x00f436e596a6b4a4ULL, 0x00168861142df0d8ULL,
+ 0x000753edfec26af5ULL, 0x000c495d7e388116ULL)},
+ {FIELD_LITERAL(0x0017085f4a346148ULL, 0x00c7cf7a37f62272ULL,
+ 0x001776e129bc5c30ULL, 0x009955134c9eef2aULL,
+ 0x001ba5bdf1df07beULL, 0x00ec39497103a55cULL,
+ 0x006578354fda6cfbULL, 0x005f02719d4f15eeULL)},
+ {FIELD_LITERAL(0x0052b9d9b5d9655dULL, 0x00d4ec7ba1b461c3ULL,
+ 0x00f95df4974f280bULL, 0x003d8e5ca11aeb51ULL,
+ 0x00d4981eb5a70b26ULL, 0x000af9a4f6659f29ULL,
+ 0x004598c846faeb43ULL, 0x0049d9a183a47670ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x000a72d23dcb3f1fULL, 0x00a3737f84011727ULL,
+ 0x00f870c0fbbf4a47ULL, 0x00a7aadd04b5c9caULL,
+ 0x000c7715c67bd072ULL, 0x00015a136afcd74eULL,
+ 0x0080d5caea499634ULL, 0x0026b448ec7514b7ULL)},
+ {FIELD_LITERAL(0x00b60167d9e7d065ULL, 0x00e60ba0d07381e8ULL,
+ 0x003a4f17b725c2d4ULL, 0x006c19fe176b64faULL,
+ 0x003b57b31af86ccbULL, 0x0021047c286180fdULL,
+ 0x00bdc8fb00c6dbb6ULL, 0x00fe4a9f4bab4f3fULL)},
+ {FIELD_LITERAL(0x0088ffc3a16111f7ULL, 0x009155e4245d0bc8ULL,
+ 0x00851d68220572d5ULL, 0x00557ace1e514d29ULL,
+ 0x0031d7c339d91022ULL, 0x00101d0ae2eaceeaULL,
+ 0x00246ab3f837b66aULL, 0x00d5216d381ff530ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x0057e7ea35f36daeULL, 0x00f47d7ad15de22eULL,
+ 0x00d757ea4b105115ULL, 0x008311457d579d7eULL,
+ 0x00b49b75b1edd4ebULL, 0x0081c7ff742fd63aULL,
+ 0x00ddda3187433df6ULL, 0x00475727d55f9c66ULL)},
+ {FIELD_LITERAL(0x00a6295218dc136aULL, 0x00563b3af0e9c012ULL,
+ 0x00d3753b0145db1bULL, 0x004550389c043dc1ULL,
+ 0x00ea94ae27401bdfULL, 0x002b0b949f2b7956ULL,
+ 0x00c63f780ad8e23cULL, 0x00e591c47d6bab15ULL)},
+ {FIELD_LITERAL(0x00416c582b058eb6ULL, 0x004107da5b2cc695ULL,
+ 0x00b3cd2556aeec64ULL, 0x00c0b418267e57a1ULL,
+ 0x001799293579bd2eULL, 0x0046ed44590e4d07ULL,
+ 0x001d7459b3630a1eULL, 0x00c6afba8b6696aaULL)},
+ }}, {{
+ {FIELD_LITERAL(0x008d6009b26da3f8ULL, 0x00898e88ca06b1caULL,
+ 0x00edb22b2ed7fe62ULL, 0x00fbc93516aabe80ULL,
+ 0x008b4b470c42ce0dULL, 0x00e0032ba7d0dcbbULL,
+ 0x00d76da3a956ecc8ULL, 0x007f20fe74e3852aULL)},
+ {FIELD_LITERAL(0x002419222c607674ULL, 0x00a7f23af89188b3ULL,
+ 0x00ad127284e73d1cULL, 0x008bba582fae1c51ULL,
+ 0x00fc6aa7ca9ecab1ULL, 0x003df5319eb6c2baULL,
+ 0x002a05af8a8b199aULL, 0x004bf8354558407cULL)},
+ {FIELD_LITERAL(0x00ce7d4a30f0fcbfULL, 0x00d02c272629f03dULL,
+ 0x0048c001f7400bc2ULL, 0x002c21368011958dULL,
+ 0x0098a550391e96b5ULL, 0x002d80b66390f379ULL,
+ 0x001fa878760cc785ULL, 0x001adfce54b613d5ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x001ed4dc71fa2523ULL, 0x005d0bff19bf9b5cULL,
+ 0x00c3801cee065a64ULL, 0x001ed0b504323fbfULL,
+ 0x0003ab9fdcbbc593ULL, 0x00df82070178b8d2ULL,
+ 0x00a2bcaa9c251f85ULL, 0x00c628a3674bd02eULL)},
+ {FIELD_LITERAL(0x006b7a0674f9f8deULL, 0x00a742414e5c7cffULL,
+ 0x0041cbf3c6e13221ULL, 0x00e3a64fd207af24ULL,
+ 0x0087c05f15fbe8d1ULL, 0x004c50936d9e8a33ULL,
+ 0x001306ec21042b6dULL, 0x00a4f4137d1141c2ULL)},
+ {FIELD_LITERAL(0x0009e6fb921568b0ULL, 0x00b3c60120219118ULL,
+ 0x002a6c3460dd503aULL, 0x009db1ef11654b54ULL,
+ 0x0063e4bf0be79601ULL, 0x00670d34bb2592b9ULL,
+ 0x00dcee2f6c4130ceULL, 0x00b2682e88e77f54ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x000d5b4b3da135abULL, 0x00838f3e5064d81dULL,
+ 0x00d44eb50f6d94edULL, 0x0008931ab502ac6dULL,
+ 0x00debe01ca3d3586ULL, 0x0025c206775f0641ULL,
+ 0x005ad4b6ae912763ULL, 0x007e2c318ad8f247ULL)},
+ {FIELD_LITERAL(0x00ddbe0750dd1addULL, 0x004b3c7b885844b8ULL,
+ 0x00363e7ecf12f1aeULL, 0x0062e953e6438f9dULL,
+ 0x0023cc73b076afe9ULL, 0x00b09fa083b4da32ULL,
+ 0x00c7c3d2456c541dULL, 0x005b591ec6b694d4ULL)},
+ {FIELD_LITERAL(0x0028656e19d62fcfULL, 0x0052a4af03df148dULL,
+ 0x00122765ddd14e42ULL, 0x00f2252904f67157ULL,
+ 0x004741965b636f3aULL, 0x006441d296132cb9ULL,
+ 0x005e2106f956a5b7ULL, 0x00247029592d335cULL)},
+ }}, {{
+ {FIELD_LITERAL(0x003fe038eb92f894ULL, 0x000e6da1b72e8e32ULL,
+ 0x003a1411bfcbe0faULL, 0x00b55d473164a9e4ULL,
+ 0x00b9a775ac2df48dULL, 0x0002ddf350659e21ULL,
+ 0x00a279a69eb19cb3ULL, 0x00f844eab25cba44ULL)},
+ {FIELD_LITERAL(0x00c41d1f9c1f1ac1ULL, 0x007b2df4e9f19146ULL,
+ 0x00b469355fd5ba7aULL, 0x00b5e1965afc852aULL,
+ 0x00388d5f1e2d8217ULL, 0x0022079e4c09ae93ULL,
+ 0x0014268acd4ef518ULL, 0x00c1dd8d9640464cULL)},
+ {FIELD_LITERAL(0x0038526adeed0c55ULL, 0x00dd68c607e3fe85ULL,
+ 0x00f746ddd48a5d57ULL, 0x0042f2952b963b7cULL,
+ 0x001cbbd6876d5ec2ULL, 0x005e341470bca5c2ULL,
+ 0x00871d41e085f413ULL, 0x00e53ab098f45732ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x004d51124797c831ULL, 0x008f5ae3750347adULL,
+ 0x0070ced94c1a0c8eULL, 0x00f6db2043898e64ULL,
+ 0x000d00c9a5750cd0ULL, 0x000741ec59bad712ULL,
+ 0x003c9d11aab37b7fULL, 0x00a67ba169807714ULL)},
+ {FIELD_LITERAL(0x00adb2c1566e8b8fULL, 0x0096c68a35771a9aULL,
+ 0x00869933356f334aULL, 0x00ba9c93459f5962ULL,
+ 0x009ec73fb6e8ca4bULL, 0x003c3802c27202e1ULL,
+ 0x0031f5b733e0c008ULL, 0x00f9058c19611fa9ULL)},
+ {FIELD_LITERAL(0x00238f01814a3421ULL, 0x00c325a44b6cce28ULL,
+ 0x002136f97aeb0e73ULL, 0x000cac8268a4afe2ULL,
+ 0x0022fd218da471b3ULL, 0x009dcd8dfff8def9ULL,
+ 0x00cb9f8181d999bbULL, 0x00143ae56edea349ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x0000623bf87622c5ULL, 0x00a1966fdd069496ULL,
+ 0x00c315b7b812f9fcULL, 0x00bdf5efcd128b97ULL,
+ 0x001d464f532e3e16ULL, 0x003cd94f081bfd7eULL,
+ 0x00ed9dae12ce4009ULL, 0x002756f5736eee70ULL)},
+ {FIELD_LITERAL(0x00a5187e6ee7341bULL, 0x00e6d52e82d83b6eULL,
+ 0x00df3c41323094a7ULL, 0x00b3324f444e9de9ULL,
+ 0x00689eb21a35bfe5ULL, 0x00f16363becd548dULL,
+ 0x00e187cc98e7f60fULL, 0x00127d9062f0ccabULL)},
+ {FIELD_LITERAL(0x004ad71b31c29e40ULL, 0x00a5fcace12fae29ULL,
+ 0x004425b5597280edULL, 0x00e7ef5d716c3346ULL,
+ 0x0010b53ada410ac8ULL, 0x0092310226060c9bULL,
+ 0x0091c26128729c7eULL, 0x0088b42900f8ec3bULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00f1e26e9762d4a8ULL, 0x00d9d74082183414ULL,
+ 0x00ffec9bd57a0282ULL, 0x000919e128fd497aULL,
+ 0x00ab7ae7d00fe5f8ULL, 0x0054dc442851ff68ULL,
+ 0x00c9ebeb3b861687ULL, 0x00507f7cab8b698fULL)},
+ {FIELD_LITERAL(0x00c13c5aae3ae341ULL, 0x009c6c9ed98373e7ULL,
+ 0x00098f26864577a8ULL, 0x0015b886e9488b45ULL,
+ 0x0037692c42aadba5ULL, 0x00b83170b8e7791cULL,
+ 0x001670952ece1b44ULL, 0x00fd932a39276da2ULL)},
+ {FIELD_LITERAL(0x0081a3259bef3398ULL, 0x005480fff416107bULL,
+ 0x00ce4f607d21be98ULL, 0x003ffc084b41df9bULL,
+ 0x0043d0bb100502d1ULL, 0x00ec35f575ba3261ULL,
+ 0x00ca18f677300ef3ULL, 0x00e8bb0a827d8548ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00df76b3328ada72ULL, 0x002e20621604a7c2ULL,
+ 0x00f910638a105b09ULL, 0x00ef4724d96ef2cdULL,
+ 0x00377d83d6b8a2f7ULL, 0x00b4f48805ade324ULL,
+ 0x001cd5da8b152018ULL, 0x0045af671a20ca7fULL)},
+ {FIELD_LITERAL(0x009ae3b93a56c404ULL, 0x004a410b7a456699ULL,
+ 0x00023a619355e6b2ULL, 0x009cdc7297387257ULL,
+ 0x0055b94d4ae70d04ULL, 0x002cbd607f65b005ULL,
+ 0x003208b489697166ULL, 0x00ea2aa058867370ULL)},
+ {FIELD_LITERAL(0x00f29d2598ee3f32ULL, 0x00b4ac5385d82adcULL,
+ 0x007633eaf04df19bULL, 0x00aa2d3d77ceab01ULL,
+ 0x004a2302fcbb778aULL, 0x00927f225d5afa34ULL,
+ 0x004a8e9d5047f237ULL, 0x008224ae9dbce530ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x001cf640859b02f8ULL, 0x00758d1d5d5ce427ULL,
+ 0x00763c784ef4604cULL, 0x005fa81aee205270ULL,
+ 0x00ac537bfdfc44cbULL, 0x004b919bd342d670ULL,
+ 0x00238508d9bf4b7aULL, 0x00154888795644f3ULL)},
+ {FIELD_LITERAL(0x00c845923c084294ULL, 0x00072419a201bc25ULL,
+ 0x0045f408b5f8e669ULL, 0x00e9d6a186b74dfeULL,
+ 0x00e19108c68fa075ULL, 0x0017b91d874177b7ULL,
+ 0x002f0ca2c7912c5aULL, 0x009400aa385a90a2ULL)},
+ {FIELD_LITERAL(0x0071110b01482184ULL, 0x00cfed0044f2bef8ULL,
+ 0x0034f2901cf4662eULL, 0x003b4ae2a67f9834ULL,
+ 0x00cca9b96fe94810ULL, 0x00522507ae77abd0ULL,
+ 0x00bac7422721e73eULL, 0x0066622b0f3a62b0ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00f8ac5cf4705b6aULL, 0x00867d82dcb457e3ULL,
+ 0x007e13ab2ccc2ce9ULL, 0x009ee9a018d3930eULL,
+ 0x008370f8ecb42df8ULL, 0x002d9f019add263eULL,
+ 0x003302385b92d196ULL, 0x00a15654536e2c0cULL)},
+ {FIELD_LITERAL(0x0026ef1614e160afULL, 0x00c023f9edfc9c76ULL,
+ 0x00cff090da5f57baULL, 0x0076db7a66643ae9ULL,
+ 0x0019462f8c646999ULL, 0x008fec00b3854b22ULL,
+ 0x00d55041692a0a1cULL, 0x0065db894215ca00ULL)},
+ {FIELD_LITERAL(0x00a925036e0a451cULL, 0x002a0390c36b6cc1ULL,
+ 0x00f27020d90894f4ULL, 0x008d90d52cbd3d7fULL,
+ 0x00e1d0137392f3b8ULL, 0x00f017c158b51a8fULL,
+ 0x00cac313d3ed7dbcULL, 0x00b99a81e3eb42d3ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00b54850275fe626ULL, 0x0053a3fd1ec71140ULL,
+ 0x00e3d2d7dbe096faULL, 0x00e4ac7b595cce4cULL,
+ 0x0077bad449c0a494ULL, 0x00b7c98814afd5b3ULL,
+ 0x0057226f58486cf9ULL, 0x00b1557154f0cc57ULL)},
+ {FIELD_LITERAL(0x008cc9cd236315c0ULL, 0x0031d9c5b39fda54ULL,
+ 0x00a5713ef37e1171ULL, 0x00293d5ae2886325ULL,
+ 0x00c4aba3e05015e1ULL, 0x0003f35ef78e4fc6ULL,
+ 0x0039d6bd3ac1527bULL, 0x0019d7c3afb77106ULL)},
+ {FIELD_LITERAL(0x007b162931a985afULL, 0x00ad40a2e0daa713ULL,
+ 0x006df27c4009f118ULL, 0x00503e9f4e2e8becULL,
+ 0x00751a77c82c182dULL, 0x000298937769245bULL,
+ 0x00ffb1e8fabf9ee5ULL, 0x0008334706e09abeULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00dbca4e98a7dcd9ULL, 0x00ee29cfc78bde99ULL,
+ 0x00e4a3b6995f52e9ULL, 0x0045d70189ae8096ULL,
+ 0x00fd2a8a3b9b0d1bULL, 0x00af1793b107d8e1ULL,
+ 0x00dbf92cbe4afa20ULL, 0x00da60f798e3681dULL)},
+ {FIELD_LITERAL(0x004246bfcecc627aULL, 0x004ba431246c03a4ULL,
+ 0x00bd1d101872d497ULL, 0x003b73d3f185ee16ULL,
+ 0x001feb2e2678c0e3ULL, 0x00ff13c5a89dec76ULL,
+ 0x00ed06042e771d8fULL, 0x00a4fd2a897a83ddULL)},
+ {FIELD_LITERAL(0x009a4a3be50d6597ULL, 0x00de3165fc5a1096ULL,
+ 0x004f3f56e345b0c7ULL, 0x00f7bf721d5ab8bcULL,
+ 0x004313e47b098c50ULL, 0x00e4c7d5c0e1adbbULL,
+ 0x002e3e3db365051eULL, 0x00a480c2cd6a96fbULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00417fa30a7119edULL, 0x00af257758419751ULL,
+ 0x00d358a487b463d4ULL, 0x0089703cc720b00dULL,
+ 0x00ce56314ff7f271ULL, 0x0064db171ade62c1ULL,
+ 0x00640b36d4a22fedULL, 0x00424eb88696d23fULL)},
+ {FIELD_LITERAL(0x004ede34af2813f3ULL, 0x00d4a8e11c9e8216ULL,
+ 0x004796d5041de8a5ULL, 0x00c4c6b4d21cc987ULL,
+ 0x00e8a433ee07fa1eULL, 0x0055720b5abcc5a1ULL,
+ 0x008873ea9c74b080ULL, 0x005b3fec1ab65d48ULL)},
+ {FIELD_LITERAL(0x0047e5277db70ec5ULL, 0x000a096c66db7d6bULL,
+ 0x00b4164cc1730159ULL, 0x004a9f783fe720feULL,
+ 0x00a8177b94449dbcULL, 0x0095a24ff49a599fULL,
+ 0x0069c1c578250cbcULL, 0x00452019213debf4ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x0021ce99e09ebda3ULL, 0x00fcbd9f91875ad0ULL,
+ 0x009bbf6b7b7a0b5fULL, 0x00388886a69b1940ULL,
+ 0x00926a56d0f81f12ULL, 0x00e12903c3358d46ULL,
+ 0x005dfce4e8e1ce9dULL, 0x0044cfa94e2f7e23ULL)},
+ {FIELD_LITERAL(0x001bd59c09e982eaULL, 0x00f72daeb937b289ULL,
+ 0x0018b76dca908e0eULL, 0x00edb498512384adULL,
+ 0x00ce0243b6cc9538ULL, 0x00f96ff690cb4e70ULL,
+ 0x007c77bf9f673c8dULL, 0x005bf704c088a528ULL)},
+ {FIELD_LITERAL(0x0093d4628dcb33beULL, 0x0095263d51d42582ULL,
+ 0x0049b3222458fe06ULL, 0x00e7fce73b653a7fULL,
+ 0x003ca2ebce60b369ULL, 0x00c5de239a32bea4ULL,
+ 0x0063b8b3d71fb6bfULL, 0x0039aeeb78a1a839ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x007dc52da400336cULL, 0x001fded1e15b9457ULL,
+ 0x00902e00f5568e3aULL, 0x00219bef40456d2dULL,
+ 0x005684161fb3dbc9ULL, 0x004a4e9be49a76eaULL,
+ 0x006e685ae88b78ffULL, 0x0021c42f13042d3cULL)},
+ {FIELD_LITERAL(0x00fb22bb5fd3ce50ULL, 0x0017b48aada7ae54ULL,
+ 0x00fd5c44ad19a536ULL, 0x000ccc4e4e55e45cULL,
+ 0x00fd637d45b4c3f5ULL, 0x0038914e023c37cfULL,
+ 0x00ac1881d6a8d898ULL, 0x00611ed8d3d943a8ULL)},
+ {FIELD_LITERAL(0x0056e2259d113d2bULL, 0x00594819b284ec16ULL,
+ 0x00c7bf794bb36696ULL, 0x00721ee75097cdc6ULL,
+ 0x00f71be9047a2892ULL, 0x00df6ba142564edfULL,
+ 0x0069580b7a184e8dULL, 0x00f056e38fca0feeULL)},
+ }}, {{
+ {FIELD_LITERAL(0x009df98566a18c6dULL, 0x00cf3a200968f219ULL,
+ 0x0044ba60da6d9086ULL, 0x00dbc9c0e344da03ULL,
+ 0x000f9401c4466855ULL, 0x00d46a57c5b0a8d1ULL,
+ 0x00875a635d7ac7c6ULL, 0x00ef4a933b7e0ae6ULL)},
+ {FIELD_LITERAL(0x005e8694077a1535ULL, 0x008bef75f71c8f1dULL,
+ 0x000a7c1316423511ULL, 0x00906e1d70604320ULL,
+ 0x003fc46c1a2ffbd6ULL, 0x00d1d5022e68f360ULL,
+ 0x002515fba37bbf46ULL, 0x00ca16234e023b44ULL)},
+ {FIELD_LITERAL(0x00787c99561f4690ULL, 0x00a857a8c1561f27ULL,
+ 0x00a10df9223c09feULL, 0x00b98a9562e3b154ULL,
+ 0x004330b8744c3ed2ULL, 0x00e06812807ec5c4ULL,
+ 0x00e4cf6a7db9f1e3ULL, 0x00d95b089f132a34ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x002922b39ca33eecULL, 0x0090d12a5f3ab194ULL,
+ 0x00ab60c02fb5f8edULL, 0x00188d292abba1cfULL,
+ 0x00e10edec9698f6eULL, 0x0069a4d9934133c8ULL,
+ 0x0024aac40e6d3d06ULL, 0x001702c2177661b0ULL)},
+ {FIELD_LITERAL(0x00139078397030bdULL, 0x000e3c447e859a00ULL,
+ 0x0064a5b334c82393ULL, 0x00b8aabeb7358093ULL,
+ 0x00020778bb9ae73bULL, 0x0032ee94c7892a18ULL,
+ 0x008215253cb41bdaULL, 0x005e2797593517aeULL)},
+ {FIELD_LITERAL(0x0083765a5f855d4aULL, 0x0051b6d1351b8ee2ULL,
+ 0x00116de548b0f7bbULL, 0x0087bd88703affa0ULL,
+ 0x0095b2cc34d7fdd2ULL, 0x0084cd81b53f0bc8ULL,
+ 0x008562fc995350edULL, 0x00a39abb193651e3ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x0019e23f0474b114ULL, 0x00eb94c2ad3b437eULL,
+ 0x006ddb34683b75acULL, 0x00391f9209b564c6ULL,
+ 0x00083b3bb3bff7aaULL, 0x00eedcd0f6dceefcULL,
+ 0x00b50817f794fe01ULL, 0x0036474deaaa75c9ULL)},
+ {FIELD_LITERAL(0x0091868594265aa2ULL, 0x00797accae98ca6dULL,
+ 0x0008d8c5f0f8a184ULL, 0x00d1f4f1c2b2fe6eULL,
+ 0x0036783dfb48a006ULL, 0x008c165120503527ULL,
+ 0x0025fd780058ce9bULL, 0x0068beb007be7d27ULL)},
+ {FIELD_LITERAL(0x00d0ff88aa7c90c2ULL, 0x00b2c60dacf53394ULL,
+ 0x0094a7284d9666d6ULL, 0x00bed9022ce7a19dULL,
+ 0x00c51553f0cd7682ULL, 0x00c3fb870b124992ULL,
+ 0x008d0bc539956c9bULL, 0x00fc8cf258bb8885ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x003667bf998406f8ULL, 0x0000115c43a12975ULL,
+ 0x001e662f3b20e8fdULL, 0x0019ffa534cb24ebULL,
+ 0x00016be0dc8efb45ULL, 0x00ff76a8b26243f5ULL,
+ 0x00ae20d241a541e3ULL, 0x0069bd6af13cd430ULL)},
+ {FIELD_LITERAL(0x0045fdc16487cda3ULL, 0x00b2d8e844cf2ed7ULL,
+ 0x00612c50e88c1607ULL, 0x00a08aabc66c1672ULL,
+ 0x006031fdcbb24d97ULL, 0x001b639525744b93ULL,
+ 0x004409d62639ab17ULL, 0x00a1853d0347ab1dULL)},
+ {FIELD_LITERAL(0x0075a1a56ebf5c21ULL, 0x00a3e72be9ac53edULL,
+ 0x00efcde1629170c2ULL, 0x0004225fe91ef535ULL,
+ 0x0088049fc73dfda7ULL, 0x004abc74857e1288ULL,
+ 0x0024e2434657317cULL, 0x00d98cb3d3e5543cULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00b4b53eab6bdb19ULL, 0x009b22d8b43711d0ULL,
+ 0x00d948b9d961785dULL, 0x00cb167b6f279eadULL,
+ 0x00191de3a678e1c9ULL, 0x00d9dd9511095c2eULL,
+ 0x00f284324cd43067ULL, 0x00ed74fa535151ddULL)},
+ {FIELD_LITERAL(0x007e32c049b5c477ULL, 0x009d2bfdbd9bcfd8ULL,
+ 0x00636e93045938c6ULL, 0x007fde4af7687298ULL,
+ 0x0046a5184fafa5d3ULL, 0x0079b1e7f13a359bULL,
+ 0x00875adf1fb927d6ULL, 0x00333e21c61bcad2ULL)},
+ {FIELD_LITERAL(0x00048014f73d8b8dULL, 0x0075684aa0966388ULL,
+ 0x0092be7df06dc47cULL, 0x0097cebcd0f5568aULL,
+ 0x005a7004d9c4c6a9ULL, 0x00b0ecbb659924c7ULL,
+ 0x00d90332dd492a7cULL, 0x0057fc14df11493dULL)},
+ }}, {{
+ {FIELD_LITERAL(0x0008ed8ea0ad95beULL, 0x0041d324b9709645ULL,
+ 0x00e25412257a19b4ULL, 0x0058df9f3423d8d2ULL,
+ 0x00a9ab20def71304ULL, 0x009ae0dbf8ac4a81ULL,
+ 0x00c9565977e4392aULL, 0x003c9269444baf55ULL)},
+ {FIELD_LITERAL(0x007df6cbb926830bULL, 0x00d336058ae37865ULL,
+ 0x007af47dac696423ULL, 0x0048d3011ec64ac8ULL,
+ 0x006b87666e40049fULL, 0x0036a2e0e51303d7ULL,
+ 0x00ba319bd79dbc55ULL, 0x003e2737ecc94f53ULL)},
+ {FIELD_LITERAL(0x00d296ff726272d9ULL, 0x00f6d097928fcf57ULL,
+ 0x00e0e616a55d7013ULL, 0x00deaf454ed9eac7ULL,
+ 0x0073a56bedef4d92ULL, 0x006ccfdf6fc92e19ULL,
+ 0x009d1ee1371a7218ULL, 0x00ee3c2ee4462d80ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00437bce9bccdf9dULL, 0x00e0c8e2f85dc0a3ULL,
+ 0x00c91a7073995a19ULL, 0x00856ec9fe294559ULL,
+ 0x009e4b33394b156eULL, 0x00e245b0dc497e5cULL,
+ 0x006a54e687eeaeffULL, 0x00f1cd1cd00fdb7cULL)},
+ {FIELD_LITERAL(0x008132ae5c5d8cd1ULL, 0x00121d68324a1d9fULL,
+ 0x00d6be9dafcb8c76ULL, 0x00684d9070edf745ULL,
+ 0x00519fbc96d7448eULL, 0x00388182fdc1f27eULL,
+ 0x000235baed41f158ULL, 0x00bf6cf6f1a1796aULL)},
+ {FIELD_LITERAL(0x002adc4b4d148219ULL, 0x003084ada0d3a90aULL,
+ 0x0046de8aab0f2e4eULL, 0x00452d342a67b5fdULL,
+ 0x00d4b50f01d4de21ULL, 0x00db6d9fc0cefb79ULL,
+ 0x008c184c86a462cdULL, 0x00e17c83764d42daULL)},
+ }}, {{
+ {FIELD_LITERAL(0x007b2743b9a1e01aULL, 0x007847ffd42688c4ULL,
+ 0x006c7844d610a316ULL, 0x00f0cb8b250aa4b0ULL,
+ 0x00a19060143b3ae6ULL, 0x0014eb10b77cfd80ULL,
+ 0x000170905729dd06ULL, 0x00063b5b9cd72477ULL)},
+ {FIELD_LITERAL(0x00ce382dc7993d92ULL, 0x00021153e938b4c8ULL,
+ 0x00096f7567f48f51ULL, 0x0058f81ddfe4b0d5ULL,
+ 0x00cc379a56b355c7ULL, 0x002c760770d3e819ULL,
+ 0x00ee22d1d26e5a40ULL, 0x00de6d93d5b082d7ULL)},
+ {FIELD_LITERAL(0x000a91a42c52e056ULL, 0x00185f6b77fce7eaULL,
+ 0x000803c51962f6b5ULL, 0x0022528582ba563dULL,
+ 0x0043f8040e9856d6ULL, 0x0085a29ec81fb860ULL,
+ 0x005f9a611549f5ffULL, 0x00c1f974ecbd4b06ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x005b64c6fd65ec97ULL, 0x00c1fdd7f877bc7fULL,
+ 0x000d9cc6c89f841cULL, 0x005c97b7f1aff9adULL,
+ 0x0075e3c61475d47eULL, 0x001ecb1ba8153011ULL,
+ 0x00fe7f1c8d71d40dULL, 0x003fa9757a229832ULL)},
+ {FIELD_LITERAL(0x00ffc5c89d2b0cbaULL, 0x00d363d42e3e6fc3ULL,
+ 0x0019a1a0118e2e8aULL, 0x00f7baeff48882e1ULL,
+ 0x001bd5af28c6b514ULL, 0x0055476ca2253cb2ULL,
+ 0x00d8eb1977e2ddf3ULL, 0x00b173b1adb228a1ULL)},
+ {FIELD_LITERAL(0x00f2cb99dd0ad707ULL, 0x00e1e08b6859ddd8ULL,
+ 0x000008f2d0650bccULL, 0x00d7ed392f8615c3ULL,
+ 0x00976750a94da27fULL, 0x003e83bb0ecb69baULL,
+ 0x00df8e8d15c14ac6ULL, 0x00f9f7174295d9c2ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00f11cc8e0e70bcbULL, 0x00e5dc689974e7ddULL,
+ 0x0014e409f9ee5870ULL, 0x00826e6689acbd63ULL,
+ 0x008a6f4e3d895d88ULL, 0x00b26a8da41fd4adULL,
+ 0x000fb7723f83efd7ULL, 0x009c749db0a5f6c3ULL)},
+ {FIELD_LITERAL(0x002389319450f9baULL, 0x003677f31aa1250aULL,
+ 0x0092c3db642f38cbULL, 0x00f8b64c0dfc9773ULL,
+ 0x00cd49fe3505b795ULL, 0x0068105a4090a510ULL,
+ 0x00df0ba2072a8bb6ULL, 0x00eb396143afd8beULL)},
+ {FIELD_LITERAL(0x00a0d4ecfb24cdffULL, 0x00ddaf8008ba6479ULL,
+ 0x00f0b3e36d4b0f44ULL, 0x003734bd3af1f146ULL,
+ 0x00b87e2efc75527eULL, 0x00d230df55ddab50ULL,
+ 0x002613257ae56c1dULL, 0x00bc0946d135934dULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00468711bd994651ULL, 0x0033108fa67561bfULL,
+ 0x0089d760192a54b4ULL, 0x00adc433de9f1871ULL,
+ 0x000467d05f36e050ULL, 0x007847e0f0579f7fULL,
+ 0x00a2314ad320052dULL, 0x00b3a93649f0b243ULL)},
+ {FIELD_LITERAL(0x0067f8f0c4fe26c9ULL, 0x0079c4a3cc8f67b9ULL,
+ 0x0082b1e62f23550dULL, 0x00f2d409caefd7f5ULL,
+ 0x0080e67dcdb26e81ULL, 0x0087ae993ea1f98aULL,
+ 0x00aa108becf61d03ULL, 0x001acf11efb608a3ULL)},
+ {FIELD_LITERAL(0x008225febbab50d9ULL, 0x00f3b605e4dd2083ULL,
+ 0x00a32b28189e23d2ULL, 0x00d507e5e5eb4c97ULL,
+ 0x005a1a84e302821fULL, 0x0006f54c1c5f08c7ULL,
+ 0x00a347c8cb2843f0ULL, 0x0009f73e9544bfa5ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x006c59c9ae744185ULL, 0x009fc32f1b4282cdULL,
+ 0x004d6348ca59b1acULL, 0x00105376881be067ULL,
+ 0x00af4096013147dcULL, 0x004abfb5a5cb3124ULL,
+ 0x000d2a7f8626c354ULL, 0x009c6ed568e07431ULL)},
+ {FIELD_LITERAL(0x00e828333c297f8bULL, 0x009ef3cf8c3f7e1fULL,
+ 0x00ab45f8fff31cb9ULL, 0x00c8b4178cb0b013ULL,
+ 0x00d0c50dd3260a3fULL, 0x0097126ac257f5bcULL,
+ 0x0042376cc90c705aULL, 0x001d96fdb4a1071eULL)},
+ {FIELD_LITERAL(0x00542d44d89ee1a8ULL, 0x00306642e0442d98ULL,
+ 0x0090853872b87338ULL, 0x002362cbf22dc044ULL,
+ 0x002c222adff663b8ULL, 0x0067c924495fcb79ULL,
+ 0x000e621d983c977cULL, 0x00df77a9eccb66fbULL)},
+ }}, {{
+ {FIELD_LITERAL(0x002809e4bbf1814aULL, 0x00b9e854f9fafb32ULL,
+ 0x00d35e67c10f7a67ULL, 0x008f1bcb76e748cfULL,
+ 0x004224d9515687d2ULL, 0x005ba0b774e620c4ULL,
+ 0x00b5e57db5d54119ULL, 0x00e15babe5683282ULL)},
+ {FIELD_LITERAL(0x00832d02369b482cULL, 0x00cba52ff0d93450ULL,
+ 0x003fa9c908d554dbULL, 0x008d1e357b54122fULL,
+ 0x00abd91c2dc950c6ULL, 0x007eff1df4c0ec69ULL,
+ 0x003f6aeb13fb2d31ULL, 0x00002d6179fc5b2cULL)},
+ {FIELD_LITERAL(0x0046c9eda81c9c89ULL, 0x00b60cb71c8f62fcULL,
+ 0x0022f5a683baa558ULL, 0x00f87319fccdf997ULL,
+ 0x009ca09b51ce6a22ULL, 0x005b12baf4af7d77ULL,
+ 0x008a46524a1e33e2ULL, 0x00035a77e988be0dULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00a7efe46a7dbe2fULL, 0x002f66fd55014fe7ULL,
+ 0x006a428afa1ff026ULL, 0x0056caaa9604ab72ULL,
+ 0x0033f3bcd7fac8aeULL, 0x00ccb1aa01c86764ULL,
+ 0x00158d1edf13bf40ULL, 0x009848ee76fcf3b4ULL)},
+ {FIELD_LITERAL(0x00a9e7730a819691ULL, 0x00d9cc73c4992b70ULL,
+ 0x00e299bde067de5aULL, 0x008c314eb705192aULL,
+ 0x00e7226f17e8a3ccULL, 0x0029dfd956e65a47ULL,
+ 0x0053a8e839073b12ULL, 0x006f942b2ab1597eULL)},
+ {FIELD_LITERAL(0x001c3d780ecd5e39ULL, 0x0094f247fbdcc5feULL,
+ 0x00d5c786fd527764ULL, 0x00b6f4da74f0db2aULL,
+ 0x0080f1f8badcd5fcULL, 0x00f36a373ad2e23bULL,
+ 0x00f804f9f4343bf2ULL, 0x00d1af40ec623982ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x0082aeace5f1b144ULL, 0x00f68b3108cf4dd3ULL,
+ 0x00634af01dde3020ULL, 0x000beab5df5c2355ULL,
+ 0x00e8b790d1b49b0bULL, 0x00e48d15854e36f4ULL,
+ 0x0040ab2d95f3db9fULL, 0x002711c4ed9e899aULL)},
+ {FIELD_LITERAL(0x0039343746531ebeULL, 0x00c8509d835d429dULL,
+ 0x00e79eceff6b0018ULL, 0x004abfd31e8efce5ULL,
+ 0x007bbfaaa1e20210ULL, 0x00e3be89c193e179ULL,
+ 0x001c420f4c31d585ULL, 0x00f414a315bef5aeULL)},
+ {FIELD_LITERAL(0x007c296a24990df8ULL, 0x00d5d07525a75588ULL,
+ 0x00dd8e113e94b7e7ULL, 0x007bbc58febe0cc8ULL,
+ 0x0029f51af9bfcad3ULL, 0x007e9311ec7ab6f3ULL,
+ 0x009a884de1676343ULL, 0x0050d5f2dce84be9ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x005fa020cca2450aULL, 0x00491c29db6416d8ULL,
+ 0x0037cefe3f9f9a85ULL, 0x003d405230647066ULL,
+ 0x0049e835f0fdbe89ULL, 0x00feb78ac1a0815cULL,
+ 0x00828e4b32dc9724ULL, 0x00db84f2dc8d6fd4ULL)},
+ {FIELD_LITERAL(0x0098cddc8b39549aULL, 0x006da37e3b05d22cULL,
+ 0x00ce633cfd4eb3cbULL, 0x00fda288ef526acdULL,
+ 0x0025338878c5d30aULL, 0x00f34438c4e5a1b4ULL,
+ 0x00584efea7c310f1ULL, 0x0041a551f1b660adULL)},
+ {FIELD_LITERAL(0x00d7f7a8fbd6437aULL, 0x0062872413bf3753ULL,
+ 0x00ad4bbcb43c584bULL, 0x007fe49be601d7e3ULL,
+ 0x0077c659789babf4ULL, 0x00eb45fcb06a741bULL,
+ 0x005ce244913f9708ULL, 0x0088426401736326ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x007bf562ca768d7cULL, 0x006c1f3a174e387cULL,
+ 0x00f024b447fee939ULL, 0x007e7af75f01143fULL,
+ 0x003adb70b4eed89dULL, 0x00e43544021ad79aULL,
+ 0x0091f7f7042011f6ULL, 0x0093c1a1ee3a0ddcULL)},
+ {FIELD_LITERAL(0x00a0b68ec1eb72d2ULL, 0x002c03235c0d45a0ULL,
+ 0x00553627323fe8c5ULL, 0x006186e94b17af94ULL,
+ 0x00a9906196e29f14ULL, 0x0025b3aee6567733ULL,
+ 0x007e0dd840080517ULL, 0x0018eb5801a4ba93ULL)},
+ {FIELD_LITERAL(0x00d7fe7017bf6a40ULL, 0x006e3f0624be0c42ULL,
+ 0x00ffbba205358245ULL, 0x00f9fc2cf8194239ULL,
+ 0x008d93b37bf15b4eULL, 0x006ddf2e38be8e95ULL,
+ 0x002b6e79bf5fcff9ULL, 0x00ab355da425e2deULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00938f97e20be973ULL, 0x0099141a36aaf306ULL,
+ 0x0057b0ca29e545a1ULL, 0x0085db571f9fbc13ULL,
+ 0x008b333c554b4693ULL, 0x0043ab6ef3e241cbULL,
+ 0x0054fb20aa1e5c70ULL, 0x00be0ff852760adfULL)},
+ {FIELD_LITERAL(0x003973d8938971d6ULL, 0x002aca26fa80c1f5ULL,
+ 0x00108af1faa6b513ULL, 0x00daae275d7924e6ULL,
+ 0x0053634ced721308ULL, 0x00d2355fe0bbd443ULL,
+ 0x00357612b2d22095ULL, 0x00f9bb9dd4136cf3ULL)},
+ {FIELD_LITERAL(0x002bff12cf5e03a5ULL, 0x001bdb1fa8a19cf8ULL,
+ 0x00c91c6793f84d39ULL, 0x00f869f1b2eba9afULL,
+ 0x0059bc547dc3236bULL, 0x00d91611d6d38689ULL,
+ 0x00e062daaa2c0214ULL, 0x00ed3c047cc2bc82ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x000050d70c32b31aULL, 0x001939d576d437b3ULL,
+ 0x00d709e598bf9fe6ULL, 0x00a885b34bd2ee9eULL,
+ 0x00dd4b5c08ab1a50ULL, 0x0091bebd50b55639ULL,
+ 0x00cf79ff64acdbc6ULL, 0x006067a39d826336ULL)},
+ {FIELD_LITERAL(0x0062dd0fb31be374ULL, 0x00fcc96b84c8e727ULL,
+ 0x003f64f1375e6ae3ULL, 0x0057d9b6dd1af004ULL,
+ 0x00d6a167b1103c7bULL, 0x00dd28f3180fb537ULL,
+ 0x004ff27ad7167128ULL, 0x008934c33461f2acULL)},
+ {FIELD_LITERAL(0x0065b472b7900043ULL, 0x00ba7efd2ff1064bULL,
+ 0x000b67d6c4c3020fULL, 0x0012d28469f4e46dULL,
+ 0x0031c32939703ec7ULL, 0x00b49f0bce133066ULL,
+ 0x00f7e10416181d47ULL, 0x005c90f51867eeccULL)},
+ }}, {{
+ {FIELD_LITERAL(0x0051207abd179101ULL, 0x00fc2a5c20d9c5daULL,
+ 0x00fb9d5f2701b6dfULL, 0x002dd040fdea82b8ULL,
+ 0x00f163b0738442ffULL, 0x00d9736bd68855b8ULL,
+ 0x00e0d8e93005e61cULL, 0x00df5a40b3988570ULL)},
+ {FIELD_LITERAL(0x0006918f5dfce6dcULL, 0x00d4bf1c793c57fbULL,
+ 0x0069a3f649435364ULL, 0x00e89a50e5b0cd6eULL,
+ 0x00b9f6a237e973afULL, 0x006d4ed8b104e41dULL,
+ 0x00498946a3924cd2ULL, 0x00c136ec5ac9d4f7ULL)},
+ {FIELD_LITERAL(0x0011a9c290ac5336ULL, 0x002b9a2d4a6a6533ULL,
+ 0x009a8a68c445d937ULL, 0x00361b27b07e5e5cULL,
+ 0x003c043b1755b974ULL, 0x00b7eb66cf1155eeULL,
+ 0x0077af5909eefff2ULL, 0x0098f609877cc806ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00ab13af436bf8f4ULL, 0x000bcf0a0dac8574ULL,
+ 0x00d50c864f705045ULL, 0x00c40e611debc842ULL,
+ 0x0085010489bd5caaULL, 0x007c5050acec026fULL,
+ 0x00f67d943c8da6d1ULL, 0x00de1da0278074c6ULL)},
+ {FIELD_LITERAL(0x00b373076597455fULL, 0x00e83f1af53ac0f5ULL,
+ 0x0041f63c01dc6840ULL, 0x0097dea19b0c6f4bULL,
+ 0x007f9d63b4c1572cULL, 0x00e692d492d0f5f0ULL,
+ 0x00cbcb392e83b4adULL, 0x0069c0f39ed9b1a8ULL)},
+ {FIELD_LITERAL(0x00861030012707c9ULL, 0x009fbbdc7fd4aafbULL,
+ 0x008f591d6b554822ULL, 0x00df08a41ea18adeULL,
+ 0x009d7d83e642abeaULL, 0x0098c71bda3b78ffULL,
+ 0x0022c89e7021f005ULL, 0x0044d29a3fe1e3c4ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00e748cd7b5c52f2ULL, 0x00ea9df883f89cc3ULL,
+ 0x0018970df156b6c7ULL, 0x00c5a46c2a33a847ULL,
+ 0x00cbde395e32aa09ULL, 0x0072474ebb423140ULL,
+ 0x00fb00053086a23dULL, 0x001dafcfe22d4e1fULL)},
+ {FIELD_LITERAL(0x00c903ee6d825540ULL, 0x00add6c4cf98473eULL,
+ 0x007636efed4227f1ULL, 0x00905124ae55e772ULL,
+ 0x00e6b38fab12ed53ULL, 0x0045e132b863fe55ULL,
+ 0x003974662edb366aULL, 0x00b1787052be8208ULL)},
+ {FIELD_LITERAL(0x00a614b00d775c7cULL, 0x00d7c78941cc7754ULL,
+ 0x00422dd68b5dabc4ULL, 0x00a6110f0167d28bULL,
+ 0x00685a309c252886ULL, 0x00b439ffd5143660ULL,
+ 0x003656e29ee7396fULL, 0x00c7c9b9ed5ad854ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x0040f7e7c5b37bf2ULL, 0x0064e4dc81181bbaULL,
+ 0x00a8767ae2a366b6ULL, 0x001496b4f90546f2ULL,
+ 0x002a28493f860441ULL, 0x0021f59513049a3aULL,
+ 0x00852d369a8b7ee3ULL, 0x00dd2e7d8b7d30a9ULL)},
+ {FIELD_LITERAL(0x00006e34a35d9fbcULL, 0x00eee4e48b2f019aULL,
+ 0x006b344743003a5fULL, 0x00541d514f04a7e3ULL,
+ 0x00e81f9ee7647455ULL, 0x005e2b916c438f81ULL,
+ 0x00116f8137b7eff0ULL, 0x009bd3decc7039d1ULL)},
+ {FIELD_LITERAL(0x0005d226f434110dULL, 0x00af8288b8ef21d5ULL,
+ 0x004a7a52ef181c8cULL, 0x00be0b781b4b06deULL,
+ 0x00e6e3627ded07e1ULL, 0x00e43aa342272b8bULL,
+ 0x00e86ab424577d84ULL, 0x00fb292c566e35bbULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00334f5303ea1222ULL, 0x00dfb3dbeb0a5d3eULL,
+ 0x002940d9592335c1ULL, 0x00706a7a63e8938aULL,
+ 0x005a533558bc4cafULL, 0x00558e33192022a9ULL,
+ 0x00970d9faf74c133ULL, 0x002979fcb63493caULL)},
+ {FIELD_LITERAL(0x00e38abece3c82abULL, 0x005a51f18a2c7a86ULL,
+ 0x009dafa2e86d592eULL, 0x00495a62eb688678ULL,
+ 0x00b79df74c0eb212ULL, 0x0023e8cc78b75982ULL,
+ 0x005998cb91075e13ULL, 0x00735aa9ba61bc76ULL)},
+ {FIELD_LITERAL(0x00d9f7a82ddbe628ULL, 0x00a1fc782889ae0fULL,
+ 0x0071ffda12d14b66ULL, 0x0037cf4eca7fb3d5ULL,
+ 0x00c80bc242c58808ULL, 0x0075bf8c2d08c863ULL,
+ 0x008d41f31afc52a7ULL, 0x00197962ecf38741ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x006e9f475cccf2eeULL, 0x00454b9cd506430cULL,
+ 0x00224a4fb79ee479ULL, 0x0062e3347ef0b5e2ULL,
+ 0x0034fd2a3512232aULL, 0x00b8b3cb0f457046ULL,
+ 0x00eb20165daa38ecULL, 0x00128eebc2d9c0f7ULL)},
+ {FIELD_LITERAL(0x00bfc5fa1e4ea21fULL, 0x00c21d7b6bb892e6ULL,
+ 0x00cf043f3acf0291ULL, 0x00c13f2f849b3c90ULL,
+ 0x00d1a97ebef10891ULL, 0x0061e130a445e7feULL,
+ 0x0019513fdedbf22bULL, 0x001d60c813bff841ULL)},
+ {FIELD_LITERAL(0x0019561c7fcf0213ULL, 0x00e3dca6843ebd77ULL,
+ 0x0068ea95b9ca920eULL, 0x009bdfb70f253595ULL,
+ 0x00c68f59186aa02aULL, 0x005aee1cca1c3039ULL,
+ 0x00ab79a8a937a1ceULL, 0x00b9a0e549959e6fULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00c79e0b6d97dfbdULL, 0x00917c71fd2bc6e8ULL,
+ 0x00db7529ccfb63d8ULL, 0x00be5be957f17866ULL,
+ 0x00a9e11fdc2cdac1ULL, 0x007b91a8e1f44443ULL,
+ 0x00a3065e4057d80fULL, 0x004825f5b8d5f6d4ULL)},
+ {FIELD_LITERAL(0x003e4964fa8a8fc8ULL, 0x00f6a1cdbcf41689ULL,
+ 0x00943cb18fe7fda7ULL, 0x00606dafbf34440aULL,
+ 0x005d37a86399c789ULL, 0x00e79a2a69417403ULL,
+ 0x00fe34f7e68b8866ULL, 0x0011f448ed2df10eULL)},
+ {FIELD_LITERAL(0x00f1f57efcc1fcc4ULL, 0x00513679117de154ULL,
+ 0x002e5b5b7c86d8c3ULL, 0x009f6486561f9cfbULL,
+ 0x00169e74b0170cf7ULL, 0x00900205af4af696ULL,
+ 0x006acfddb77853f3ULL, 0x00df184c90f31068ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00b37396c3320791ULL, 0x00fc7b67175c5783ULL,
+ 0x00c36d2cd73ecc38ULL, 0x0080ebcc0b328fc5ULL,
+ 0x0043a5b22b35d35dULL, 0x00466c9f1713c9daULL,
+ 0x0026ad346dcaa8daULL, 0x007c684e701183a6ULL)},
+ {FIELD_LITERAL(0x00fd579ffb691713ULL, 0x00b76af4f81c412dULL,
+ 0x00f239de96110f82ULL, 0x00e965fb437f0306ULL,
+ 0x00ca7e9436900921ULL, 0x00e487f1325fa24aULL,
+ 0x00633907de476380ULL, 0x00721c62ac5b8ea0ULL)},
+ {FIELD_LITERAL(0x00c0d54e542eb4f9ULL, 0x004ed657171c8dcfULL,
+ 0x00b743a4f7c2a39bULL, 0x00fd9f93ed6cc567ULL,
+ 0x00307fae3113e58bULL, 0x0058aa577c93c319ULL,
+ 0x00d254556f35b346ULL, 0x00491aada2203f0dULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00dff3103786ff34ULL, 0x000144553b1f20c3ULL,
+ 0x0095613baeb930e4ULL, 0x00098058275ea5d4ULL,
+ 0x007cd1402b046756ULL, 0x0074d74e4d58aee3ULL,
+ 0x005f93fc343ff69bULL, 0x00873df17296b3b0ULL)},
+ {FIELD_LITERAL(0x00c4a1fb48635413ULL, 0x00b5dd54423ad59fULL,
+ 0x009ff5d53fd24a88ULL, 0x003c98d267fc06a7ULL,
+ 0x002db7cb20013641ULL, 0x00bd1d6716e191f2ULL,
+ 0x006dbc8b29094241ULL, 0x0044bbf233dafa2cULL)},
+ {FIELD_LITERAL(0x0055838d41f531e6ULL, 0x00bf6a2dd03c81b2ULL,
+ 0x005827a061c4839eULL, 0x0000de2cbb36aac3ULL,
+ 0x002efa29d9717478ULL, 0x00f9e928cc8a77baULL,
+ 0x00c134b458def9efULL, 0x00958a182223fc48ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x000a9ee23c06881fULL, 0x002c727d3d871945ULL,
+ 0x00f47d971512d24aULL, 0x00671e816f9ef31aULL,
+ 0x00883af2cfaad673ULL, 0x00601f98583d6c9aULL,
+ 0x00b435f5adc79655ULL, 0x00ad87b71c04bff2ULL)},
+ {FIELD_LITERAL(0x007860d99db787cfULL, 0x00fda8983018f4a8ULL,
+ 0x008c8866bac4743cULL, 0x00ef471f84c82a3fULL,
+ 0x00abea5976d3b8e7ULL, 0x00714882896cd015ULL,
+ 0x00b49fae584ddac5ULL, 0x008e33a1a0b69c81ULL)},
+ {FIELD_LITERAL(0x007b6ee2c9e8a9ecULL, 0x002455dbbd89d622ULL,
+ 0x006490cf4eaab038ULL, 0x00d925f6c3081561ULL,
+ 0x00153b3047de7382ULL, 0x003b421f8bdceb6fULL,
+ 0x00761a4a5049da78ULL, 0x00980348c5202433ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x007f8a43da97dd5cULL, 0x00058539c800fc7bULL,
+ 0x0040f3cf5a28414aULL, 0x00d68dd0d95283d6ULL,
+ 0x004adce9da90146eULL, 0x00befa41c7d4f908ULL,
+ 0x007603bc2e3c3060ULL, 0x00bdf360ab3545dbULL)},
+ {FIELD_LITERAL(0x00eebfd4e2312cc3ULL, 0x00474b2564e4fc8cULL,
+ 0x003303ef14b1da9bULL, 0x003c93e0e66beb1dULL,
+ 0x0013619b0566925aULL, 0x008817c24d901bf3ULL,
+ 0x00b62bd8898d218bULL, 0x0075a7716f1e88a2ULL)},
+ {FIELD_LITERAL(0x0009218da1e6890fULL, 0x0026907f5fd02575ULL,
+ 0x004dabed5f19d605ULL, 0x003abf181870249dULL,
+ 0x00b52fd048cc92c4ULL, 0x00b6dd51e415a5c5ULL,
+ 0x00d9eb82bd2b4014ULL, 0x002c865a43b46b43ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x0070047189452f4cULL, 0x00f7ad12e1ce78d5ULL,
+ 0x00af1ba51ec44a8bULL, 0x005f39f63e667cd6ULL,
+ 0x00058eac4648425eULL, 0x00d7fdab42bea03bULL,
+ 0x0028576a5688de15ULL, 0x00af973209e77c10ULL)},
+ {FIELD_LITERAL(0x00c338b915d8fef0ULL, 0x00a893292045c39aULL,
+ 0x0028ab4f2eba6887ULL, 0x0060743cb519fd61ULL,
+ 0x0006213964093ac0ULL, 0x007c0b7a43f6266dULL,
+ 0x008e3557c4fa5bdaULL, 0x002da976de7b8d9dULL)},
+ {FIELD_LITERAL(0x0048729f8a8b6dcdULL, 0x00fe23b85cc4d323ULL,
+ 0x00e7384d16e4db0eULL, 0x004a423970678942ULL,
+ 0x00ec0b763345d4baULL, 0x00c477b9f99ed721ULL,
+ 0x00c29dad3777b230ULL, 0x001c517b466f7df6ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x006366c380f7b574ULL, 0x001c7d1f09ff0438ULL,
+ 0x003e20a7301f5b22ULL, 0x00d3efb1916d28f6ULL,
+ 0x0049f4f81060ce83ULL, 0x00c69d91ea43ced1ULL,
+ 0x002b6f3e5cd269edULL, 0x005b0fb22ce9ec65ULL)},
+ {FIELD_LITERAL(0x00aa2261022d883fULL, 0x00ebcca4548010acULL,
+ 0x002528512e28a437ULL, 0x0070ca7676b66082ULL,
+ 0x0084bda170f7c6d3ULL, 0x00581b4747c9b8bbULL,
+ 0x005c96a01061c7e2ULL, 0x00fb7c4a362b5273ULL)},
+ {FIELD_LITERAL(0x00c30020eb512d02ULL, 0x0060f288283a4d26ULL,
+ 0x00b7ed13becde260ULL, 0x0075ebb74220f6e9ULL,
+ 0x00701079fcfe8a1fULL, 0x001c28fcdff58938ULL,
+ 0x002e4544b8f4df6bULL, 0x0060c5bc4f1a7d73ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00ae307cf069f701ULL, 0x005859f222dd618bULL,
+ 0x00212d6c46ec0b0dULL, 0x00a0fe4642afb62dULL,
+ 0x00420d8e4a0a8903ULL, 0x00a80ff639bdf7b0ULL,
+ 0x0019bee1490b5d8eULL, 0x007439e4b9c27a86ULL)},
+ {FIELD_LITERAL(0x00a94700032a093fULL, 0x0076e96c225216e7ULL,
+ 0x00a63a4316e45f91ULL, 0x007d8bbb4645d3b2ULL,
+ 0x00340a6ff22793ebULL, 0x006f935d4572aeb7ULL,
+ 0x00b1fb69f00afa28ULL, 0x009e8f3423161ed3ULL)},
+ {FIELD_LITERAL(0x009ef49c6b5ced17ULL, 0x00a555e6269e9f0aULL,
+ 0x007e6f1d79ec73b5ULL, 0x009ac78695a32ac4ULL,
+ 0x0001d77fbbcd5682ULL, 0x008cea1fee0aaeedULL,
+ 0x00f42bea82a53462ULL, 0x002e46ab96cafcc9ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x0051cfcc5885377aULL, 0x00dce566cb1803caULL,
+ 0x00430c7643f2c7d4ULL, 0x00dce1a1337bdcc0ULL,
+ 0x0010d5bd7283c128ULL, 0x003b1b547f9b46feULL,
+ 0x000f245e37e770abULL, 0x007b72511f022b37ULL)},
+ {FIELD_LITERAL(0x0060db815bc4786cULL, 0x006fab25beedc434ULL,
+ 0x00c610d06084797cULL, 0x000c48f08537bec0ULL,
+ 0x0031aba51c5b93daULL, 0x007968fa6e01f347ULL,
+ 0x0030070da52840c6ULL, 0x00c043c225a4837fULL)},
+ {FIELD_LITERAL(0x001bcfd00649ee93ULL, 0x006dceb47e2a0fd5ULL,
+ 0x00f2cebda0cf8fd0ULL, 0x00b6b9d9d1fbdec3ULL,
+ 0x00815262e6490611ULL, 0x00ef7f5ce3176760ULL,
+ 0x00e49cd0c998d58bULL, 0x005fc6cc269ba57cULL)},
+ }}, {{
+ {FIELD_LITERAL(0x008940211aa0d633ULL, 0x00addae28136571dULL,
+ 0x00d68fdbba20d673ULL, 0x003bc6129bc9e21aULL,
+ 0x000346cf184ebe9aULL, 0x0068774d741ebc7fULL,
+ 0x0019d5e9e6966557ULL, 0x0003cbd7f981b651ULL)},
+ {FIELD_LITERAL(0x004a2902926f8d3fULL, 0x00ad79b42637ab75ULL,
+ 0x0088f60b90f2d4e8ULL, 0x0030f54ef0e398c4ULL,
+ 0x00021dc9bf99681eULL, 0x007ebf66fde74ee3ULL,
+ 0x004ade654386e9a4ULL, 0x00e7485066be4c27ULL)},
+ {FIELD_LITERAL(0x00445f1263983be0ULL, 0x004cf371dda45e6aULL,
+ 0x00744a89d5a310e7ULL, 0x001f20ce4f904833ULL,
+ 0x00e746edebe66e29ULL, 0x000912ab1f6c153dULL,
+ 0x00f61d77d9b2444cULL, 0x0001499cd6647610ULL)},
}}
}
};
@@ -345,133 +1065,421 @@ const struct curve448_precomputed_s *curve448_precomputed_base
static const niels_t curve448_wnaf_base_table[32] = {
{{
- {FIELD_LITERAL(0x00303cda6feea532,0x00860f1d5a3850e4,0x00226b9fa4728ccd,0x00e822938a0a0c0c,0x00263a61c9ea9216,0x001204029321b828,0x006a468360983c65,0x0002846f0a782143)},
- {FIELD_LITERAL(0x00303cda6feea532,0x00860f1d5a3850e4,0x00226b9fa4728ccd,0x006822938a0a0c0c,0x00263a61c9ea9215,0x001204029321b828,0x006a468360983c65,0x0082846f0a782143)},
- {FIELD_LITERAL(0x00ef8e22b275198d,0x00b0eb141a0b0e8b,0x001f6789da3cb38c,0x006d2ff8ed39073e,0x00610bdb69a167f3,0x00571f306c9689b4,0x00f557e6f84b2df8,0x002affd38b2c86db)},
+ {FIELD_LITERAL(0x00303cda6feea532ULL, 0x00860f1d5a3850e4ULL,
+ 0x00226b9fa4728ccdULL, 0x00e822938a0a0c0cULL,
+ 0x00263a61c9ea9216ULL, 0x001204029321b828ULL,
+ 0x006a468360983c65ULL, 0x0002846f0a782143ULL)},
+ {FIELD_LITERAL(0x00303cda6feea532ULL, 0x00860f1d5a3850e4ULL,
+ 0x00226b9fa4728ccdULL, 0x006822938a0a0c0cULL,
+ 0x00263a61c9ea9215ULL, 0x001204029321b828ULL,
+ 0x006a468360983c65ULL, 0x0082846f0a782143ULL)},
+ {FIELD_LITERAL(0x00ef8e22b275198dULL, 0x00b0eb141a0b0e8bULL,
+ 0x001f6789da3cb38cULL, 0x006d2ff8ed39073eULL,
+ 0x00610bdb69a167f3ULL, 0x00571f306c9689b4ULL,
+ 0x00f557e6f84b2df8ULL, 0x002affd38b2c86dbULL)},
}}, {{
- {FIELD_LITERAL(0x00cea0fc8d2e88b5,0x00821612d69f1862,0x0074c283b3e67522,0x005a195ba05a876d,0x000cddfe557feea4,0x008046c795bcc5e5,0x00540969f4d6e119,0x00d27f96d6b143d5)},
- {FIELD_LITERAL(0x000c3b1019d474e8,0x00e19533e4952284,0x00cc9810ba7c920a,0x00f103d2785945ac,0x00bfa5696cc69b34,0x00a8d3d51e9ca839,0x005623cb459586b9,0x00eae7ce1cd52e9e)},
- {FIELD_LITERAL(0x0005a178751dd7d8,0x002cc3844c69c42f,0x00acbfe5efe10539,0x009c20f43431a65a,0x008435d96374a7b3,0x009ee57566877bd3,0x0044691725ed4757,0x001e87bb2fe2c6b2)},
+ {FIELD_LITERAL(0x00cea0fc8d2e88b5ULL, 0x00821612d69f1862ULL,
+ 0x0074c283b3e67522ULL, 0x005a195ba05a876dULL,
+ 0x000cddfe557feea4ULL, 0x008046c795bcc5e5ULL,
+ 0x00540969f4d6e119ULL, 0x00d27f96d6b143d5ULL)},
+ {FIELD_LITERAL(0x000c3b1019d474e8ULL, 0x00e19533e4952284ULL,
+ 0x00cc9810ba7c920aULL, 0x00f103d2785945acULL,
+ 0x00bfa5696cc69b34ULL, 0x00a8d3d51e9ca839ULL,
+ 0x005623cb459586b9ULL, 0x00eae7ce1cd52e9eULL)},
+ {FIELD_LITERAL(0x0005a178751dd7d8ULL, 0x002cc3844c69c42fULL,
+ 0x00acbfe5efe10539ULL, 0x009c20f43431a65aULL,
+ 0x008435d96374a7b3ULL, 0x009ee57566877bd3ULL,
+ 0x0044691725ed4757ULL, 0x001e87bb2fe2c6b2ULL)},
}}, {{
- {FIELD_LITERAL(0x000cedc4debf7a04,0x002ffa45000470ac,0x002e9f9678201915,0x0017da1208c4fe72,0x007d558cc7d656cb,0x0037a827287cf289,0x00142472d3441819,0x009c21f166cf8dd1)},
- {FIELD_LITERAL(0x003ef83af164b2f2,0x000949a5a0525d0d,0x00f4498186cac051,0x00e77ac09ef126d2,0x0073ae0b2c9296e9,0x001c163f6922e3ed,0x0062946159321bea,0x00cfb79b22990b39)},
- {FIELD_LITERAL(0x00b001431ca9e654,0x002d7e5eabcc9a3a,0x0052e8114c2f6747,0x0079ac4f94487f92,0x00bffd919b5d749c,0x00261f92ad15e620,0x00718397b7a97895,0x00c1443e6ebbc0c4)},
+ {FIELD_LITERAL(0x000cedc4debf7a04ULL, 0x002ffa45000470acULL,
+ 0x002e9f9678201915ULL, 0x0017da1208c4fe72ULL,
+ 0x007d558cc7d656cbULL, 0x0037a827287cf289ULL,
+ 0x00142472d3441819ULL, 0x009c21f166cf8dd1ULL)},
+ {FIELD_LITERAL(0x003ef83af164b2f2ULL, 0x000949a5a0525d0dULL,
+ 0x00f4498186cac051ULL, 0x00e77ac09ef126d2ULL,
+ 0x0073ae0b2c9296e9ULL, 0x001c163f6922e3edULL,
+ 0x0062946159321beaULL, 0x00cfb79b22990b39ULL)},
+ {FIELD_LITERAL(0x00b001431ca9e654ULL, 0x002d7e5eabcc9a3aULL,
+ 0x0052e8114c2f6747ULL, 0x0079ac4f94487f92ULL,
+ 0x00bffd919b5d749cULL, 0x00261f92ad15e620ULL,
+ 0x00718397b7a97895ULL, 0x00c1443e6ebbc0c4ULL)},
}}, {{
- {FIELD_LITERAL(0x00eacd90c1e0a049,0x008977935b149fbe,0x0004cb9ba11c93dc,0x009fbd5b3470844d,0x004bc18c9bfc22cf,0x0057679a991839f3,0x00ef15b76fb4092e,0x0074a5173a225041)},
- {FIELD_LITERAL(0x003f5f9d7ec4777b,0x00ab2e733c919c94,0x001bb6c035245ae5,0x00a325a49a883630,0x0033e9a9ea3cea2f,0x00e442a1eaa0e844,0x00b2116d5b0e71b8,0x00c16abed6d64047)},
- {FIELD_LITERAL(0x00c560b5ed051165,0x001945adc5d65094,0x00e221865710f910,0x00cc12bc9e9b8ceb,0x004faa9518914e35,0x0017476d89d42f6d,0x00b8f637c8fa1c8b,0x0088c7d2790864b8)},
+ {FIELD_LITERAL(0x00eacd90c1e0a049ULL, 0x008977935b149fbeULL,
+ 0x0004cb9ba11c93dcULL, 0x009fbd5b3470844dULL,
+ 0x004bc18c9bfc22cfULL, 0x0057679a991839f3ULL,
+ 0x00ef15b76fb4092eULL, 0x0074a5173a225041ULL)},
+ {FIELD_LITERAL(0x003f5f9d7ec4777bULL, 0x00ab2e733c919c94ULL,
+ 0x001bb6c035245ae5ULL, 0x00a325a49a883630ULL,
+ 0x0033e9a9ea3cea2fULL, 0x00e442a1eaa0e844ULL,
+ 0x00b2116d5b0e71b8ULL, 0x00c16abed6d64047ULL)},
+ {FIELD_LITERAL(0x00c560b5ed051165ULL, 0x001945adc5d65094ULL,
+ 0x00e221865710f910ULL, 0x00cc12bc9e9b8cebULL,
+ 0x004faa9518914e35ULL, 0x0017476d89d42f6dULL,
+ 0x00b8f637c8fa1c8bULL, 0x0088c7d2790864b8ULL)},
}}, {{
- {FIELD_LITERAL(0x00ef7eafc1c69be6,0x0085d3855778fbea,0x002c8d5b450cb6f5,0x004e77de5e1e7fec,0x0047c057893abded,0x001b430b85d51e16,0x00965c7b45640c3c,0x00487b2bb1162b97)},
- {FIELD_LITERAL(0x0099c73a311beec2,0x00a3eff38d8912ad,0x002efa9d1d7e8972,0x00f717ae1e14d126,0x002833f795850c8b,0x0066c12ad71486bd,0x00ae9889da4820eb,0x00d6044309555c08)},
- {FIELD_LITERAL(0x004b1c5283d15e41,0x00669d8ea308ff75,0x0004390233f762a1,0x00e1d67b83cb6cec,0x003eebaa964c78b1,0x006b0aff965eb664,0x00b313d4470bdc37,0x008814ffcb3cb9d8)},
+ {FIELD_LITERAL(0x00ef7eafc1c69be6ULL, 0x0085d3855778fbeaULL,
+ 0x002c8d5b450cb6f5ULL, 0x004e77de5e1e7fecULL,
+ 0x0047c057893abdedULL, 0x001b430b85d51e16ULL,
+ 0x00965c7b45640c3cULL, 0x00487b2bb1162b97ULL)},
+ {FIELD_LITERAL(0x0099c73a311beec2ULL, 0x00a3eff38d8912adULL,
+ 0x002efa9d1d7e8972ULL, 0x00f717ae1e14d126ULL,
+ 0x002833f795850c8bULL, 0x0066c12ad71486bdULL,
+ 0x00ae9889da4820ebULL, 0x00d6044309555c08ULL)},
+ {FIELD_LITERAL(0x004b1c5283d15e41ULL, 0x00669d8ea308ff75ULL,
+ 0x0004390233f762a1ULL, 0x00e1d67b83cb6cecULL,
+ 0x003eebaa964c78b1ULL, 0x006b0aff965eb664ULL,
+ 0x00b313d4470bdc37ULL, 0x008814ffcb3cb9d8ULL)},
}}, {{
- {FIELD_LITERAL(0x009724b8ce68db70,0x007678b5ed006f3d,0x00bdf4b89c0abd73,0x00299748e04c7c6d,0x00ddd86492c3c977,0x00c5a7febfa30a99,0x00ed84715b4b02bb,0x00319568adf70486)},
- {FIELD_LITERAL(0x0070ff2d864de5bb,0x005a37eeb637ee95,0x0033741c258de160,0x00e6ca5cb1988f46,0x001ceabd92a24661,0x0030957bd500fe40,0x001c3362afe912c5,0x005187889f678bd2)},
- {FIELD_LITERAL(0x0086835fc62bbdc7,0x009c3516ca4910a1,0x00956c71f8d00783,0x0095c78fcf63235f,0x00fc7ff6ba05c222,0x00cdd8b3f8d74a52,0x00ac5ae16de8256e,0x00e9d4be8ed48624)},
+ {FIELD_LITERAL(0x009724b8ce68db70ULL, 0x007678b5ed006f3dULL,
+ 0x00bdf4b89c0abd73ULL, 0x00299748e04c7c6dULL,
+ 0x00ddd86492c3c977ULL, 0x00c5a7febfa30a99ULL,
+ 0x00ed84715b4b02bbULL, 0x00319568adf70486ULL)},
+ {FIELD_LITERAL(0x0070ff2d864de5bbULL, 0x005a37eeb637ee95ULL,
+ 0x0033741c258de160ULL, 0x00e6ca5cb1988f46ULL,
+ 0x001ceabd92a24661ULL, 0x0030957bd500fe40ULL,
+ 0x001c3362afe912c5ULL, 0x005187889f678bd2ULL)},
+ {FIELD_LITERAL(0x0086835fc62bbdc7ULL, 0x009c3516ca4910a1ULL,
+ 0x00956c71f8d00783ULL, 0x0095c78fcf63235fULL,
+ 0x00fc7ff6ba05c222ULL, 0x00cdd8b3f8d74a52ULL,
+ 0x00ac5ae16de8256eULL, 0x00e9d4be8ed48624ULL)},
}}, {{
- {FIELD_LITERAL(0x00c0ce11405df2d8,0x004e3f37b293d7b6,0x002410172e1ac6db,0x00b8dbff4bf8143d,0x003a7b409d56eb66,0x003e0f6a0dfef9af,0x0081c4e4d3645be1,0x00ce76076b127623)},
- {FIELD_LITERAL(0x00f6ee0f98974239,0x0042d89af07d3a4f,0x00846b7fe84346b5,0x006a21fc6a8d39a1,0x00ac8bc2541ff2d9,0x006d4e2a77732732,0x009a39b694cc3f2f,0x0085c0aa2a404c8f)},
- {FIELD_LITERAL(0x00b261101a218548,0x00c1cae96424277b,0x00869da0a77dd268,0x00bc0b09f8ec83ea,0x00d61027f8e82ba9,0x00aa4c85999dce67,0x00eac3132b9f3fe1,0x00fb9b0cf1c695d2)},
+ {FIELD_LITERAL(0x00c0ce11405df2d8ULL, 0x004e3f37b293d7b6ULL,
+ 0x002410172e1ac6dbULL, 0x00b8dbff4bf8143dULL,
+ 0x003a7b409d56eb66ULL, 0x003e0f6a0dfef9afULL,
+ 0x0081c4e4d3645be1ULL, 0x00ce76076b127623ULL)},
+ {FIELD_LITERAL(0x00f6ee0f98974239ULL, 0x0042d89af07d3a4fULL,
+ 0x00846b7fe84346b5ULL, 0x006a21fc6a8d39a1ULL,
+ 0x00ac8bc2541ff2d9ULL, 0x006d4e2a77732732ULL,
+ 0x009a39b694cc3f2fULL, 0x0085c0aa2a404c8fULL)},
+ {FIELD_LITERAL(0x00b261101a218548ULL, 0x00c1cae96424277bULL,
+ 0x00869da0a77dd268ULL, 0x00bc0b09f8ec83eaULL,
+ 0x00d61027f8e82ba9ULL, 0x00aa4c85999dce67ULL,
+ 0x00eac3132b9f3fe1ULL, 0x00fb9b0cf1c695d2ULL)},
}}, {{
- {FIELD_LITERAL(0x0043079295512f0d,0x0046a009861758e0,0x003ee2842a807378,0x0034cc9d1298e4fa,0x009744eb4d31b3ee,0x00afacec96650cd0,0x00ac891b313761ae,0x00e864d6d26e708a)},
- {FIELD_LITERAL(0x00a84d7c8a23b491,0x0088e19aa868b27f,0x0005986d43e78ce9,0x00f28012f0606d28,0x0017ded7e10249b3,0x005ed4084b23af9b,0x00b9b0a940564472,0x00ad9056cceeb1f4)},
- {FIELD_LITERAL(0x00db91b357fe755e,0x00a1aa544b15359c,0x00af4931a0195574,0x007686124fe11aef,0x00d1ead3c7b9ef7e,0x00aaf5fc580f8c15,0x00e727be147ee1ec,0x003c61c1e1577b86)},
+ {FIELD_LITERAL(0x0043079295512f0dULL, 0x0046a009861758e0ULL,
+ 0x003ee2842a807378ULL, 0x0034cc9d1298e4faULL,
+ 0x009744eb4d31b3eeULL, 0x00afacec96650cd0ULL,
+ 0x00ac891b313761aeULL, 0x00e864d6d26e708aULL)},
+ {FIELD_LITERAL(0x00a84d7c8a23b491ULL, 0x0088e19aa868b27fULL,
+ 0x0005986d43e78ce9ULL, 0x00f28012f0606d28ULL,
+ 0x0017ded7e10249b3ULL, 0x005ed4084b23af9bULL,
+ 0x00b9b0a940564472ULL, 0x00ad9056cceeb1f4ULL)},
+ {FIELD_LITERAL(0x00db91b357fe755eULL, 0x00a1aa544b15359cULL,
+ 0x00af4931a0195574ULL, 0x007686124fe11aefULL,
+ 0x00d1ead3c7b9ef7eULL, 0x00aaf5fc580f8c15ULL,
+ 0x00e727be147ee1ecULL, 0x003c61c1e1577b86ULL)},
}}, {{
- {FIELD_LITERAL(0x009d3fca983220cf,0x00cd11acbc853dc4,0x0017590409d27f1d,0x00d2176698082802,0x00fa01251b2838c8,0x00dd297a0d9b51c6,0x00d76c92c045820a,0x00534bc7c46c9033)},
- {FIELD_LITERAL(0x0080ed9bc9b07338,0x00fceac7745d2652,0x008a9d55f5f2cc69,0x0096ce72df301ac5,0x00f53232e7974d87,0x0071728c7ae73947,0x0090507602570778,0x00cb81cfd883b1b2)},
- {FIELD_LITERAL(0x005011aadea373da,0x003a8578ec896034,0x00f20a6535fa6d71,0x005152d31e5a87cf,0x002bac1c8e68ca31,0x00b0e323db4c1381,0x00f1d596b7d5ae25,0x00eae458097cb4e0)},
+ {FIELD_LITERAL(0x009d3fca983220cfULL, 0x00cd11acbc853dc4ULL,
+ 0x0017590409d27f1dULL, 0x00d2176698082802ULL,
+ 0x00fa01251b2838c8ULL, 0x00dd297a0d9b51c6ULL,
+ 0x00d76c92c045820aULL, 0x00534bc7c46c9033ULL)},
+ {FIELD_LITERAL(0x0080ed9bc9b07338ULL, 0x00fceac7745d2652ULL,
+ 0x008a9d55f5f2cc69ULL, 0x0096ce72df301ac5ULL,
+ 0x00f53232e7974d87ULL, 0x0071728c7ae73947ULL,
+ 0x0090507602570778ULL, 0x00cb81cfd883b1b2ULL)},
+ {FIELD_LITERAL(0x005011aadea373daULL, 0x003a8578ec896034ULL,
+ 0x00f20a6535fa6d71ULL, 0x005152d31e5a87cfULL,
+ 0x002bac1c8e68ca31ULL, 0x00b0e323db4c1381ULL,
+ 0x00f1d596b7d5ae25ULL, 0x00eae458097cb4e0ULL)},
}}, {{
- {FIELD_LITERAL(0x00920ac80f9b0d21,0x00f80f7f73401246,0x0086d37849b557d6,0x0002bd4b317b752e,0x00b26463993a42bb,0x002070422a73b129,0x00341acaa0380cb3,0x00541914dd66a1b2)},
- {FIELD_LITERAL(0x00c1513cd66abe8c,0x000139e01118944d,0x0064abbcb8080bbb,0x00b3b08202473142,0x00c629ef25da2403,0x00f0aec3310d9b7f,0x0050b2227472d8cd,0x00f6c8a922d41fb4)},
- {FIELD_LITERAL(0x001075ccf26b7b1f,0x00bb6bb213170433,0x00e9491ad262da79,0x009ef4f48d2d384c,0x008992770766f09d,0x001584396b6b1101,0x00af3f8676c9feef,0x0024603c40269118)},
+ {FIELD_LITERAL(0x00920ac80f9b0d21ULL, 0x00f80f7f73401246ULL,
+ 0x0086d37849b557d6ULL, 0x0002bd4b317b752eULL,
+ 0x00b26463993a42bbULL, 0x002070422a73b129ULL,
+ 0x00341acaa0380cb3ULL, 0x00541914dd66a1b2ULL)},
+ {FIELD_LITERAL(0x00c1513cd66abe8cULL, 0x000139e01118944dULL,
+ 0x0064abbcb8080bbbULL, 0x00b3b08202473142ULL,
+ 0x00c629ef25da2403ULL, 0x00f0aec3310d9b7fULL,
+ 0x0050b2227472d8cdULL, 0x00f6c8a922d41fb4ULL)},
+ {FIELD_LITERAL(0x001075ccf26b7b1fULL, 0x00bb6bb213170433ULL,
+ 0x00e9491ad262da79ULL, 0x009ef4f48d2d384cULL,
+ 0x008992770766f09dULL, 0x001584396b6b1101ULL,
+ 0x00af3f8676c9feefULL, 0x0024603c40269118ULL)},
}}, {{
- {FIELD_LITERAL(0x009dd7b31319527c,0x001e7ac948d873a9,0x00fa54b46ef9673a,0x0066efb8d5b02fe6,0x00754b1d3928aeae,0x0004262ac72a6f6b,0x0079b7d49a6eb026,0x003126a753540102)},
- {FIELD_LITERAL(0x009666e24f693947,0x00f714311269d45f,0x0010ffac1d0c851c,0x0066e80c37363497,0x00f1f4ad010c60b0,0x0015c87408470ff7,0x00651d5e9c7766a4,0x008138819d7116de)},
- {FIELD_LITERAL(0x003934b11c57253b,0x00ef308edf21f46e,0x00e54e99c7a16198,0x0080d57135764e63,0x00751c27b946bc24,0x00dd389ce4e9e129,0x00a1a2bfd1cd84dc,0x002fae73e5149b32)},
+ {FIELD_LITERAL(0x009dd7b31319527cULL, 0x001e7ac948d873a9ULL,
+ 0x00fa54b46ef9673aULL, 0x0066efb8d5b02fe6ULL,
+ 0x00754b1d3928aeaeULL, 0x0004262ac72a6f6bULL,
+ 0x0079b7d49a6eb026ULL, 0x003126a753540102ULL)},
+ {FIELD_LITERAL(0x009666e24f693947ULL, 0x00f714311269d45fULL,
+ 0x0010ffac1d0c851cULL, 0x0066e80c37363497ULL,
+ 0x00f1f4ad010c60b0ULL, 0x0015c87408470ff7ULL,
+ 0x00651d5e9c7766a4ULL, 0x008138819d7116deULL)},
+ {FIELD_LITERAL(0x003934b11c57253bULL, 0x00ef308edf21f46eULL,
+ 0x00e54e99c7a16198ULL, 0x0080d57135764e63ULL,
+ 0x00751c27b946bc24ULL, 0x00dd389ce4e9e129ULL,
+ 0x00a1a2bfd1cd84dcULL, 0x002fae73e5149b32ULL)},
}}, {{
- {FIELD_LITERAL(0x00911657dffb4cdd,0x00c100b7cc553d06,0x00449d075ec467cc,0x007062100bc64e70,0x0043cf86f7bd21e7,0x00f401dc4b797dea,0x005224afb2f62e65,0x00d1ede3fb5a42be)},
- {FIELD_LITERAL(0x00f2ba36a41aa144,0x00a0c22d946ee18f,0x008aae8ef9a14f99,0x00eef4d79b19bb36,0x008e75ce3d27b1fc,0x00a65daa03b29a27,0x00d9cc83684eb145,0x009e1ed80cc2ed74)},
- {FIELD_LITERAL(0x00bed953d1997988,0x00b93ed175a24128,0x00871c5963fb6365,0x00ca2df20014a787,0x00f5d9c1d0b34322,0x00f6f5942818db0a,0x004cc091f49c9906,0x00e8a188a60bff9f)},
+ {FIELD_LITERAL(0x00911657dffb4cddULL, 0x00c100b7cc553d06ULL,
+ 0x00449d075ec467ccULL, 0x007062100bc64e70ULL,
+ 0x0043cf86f7bd21e7ULL, 0x00f401dc4b797deaULL,
+ 0x005224afb2f62e65ULL, 0x00d1ede3fb5a42beULL)},
+ {FIELD_LITERAL(0x00f2ba36a41aa144ULL, 0x00a0c22d946ee18fULL,
+ 0x008aae8ef9a14f99ULL, 0x00eef4d79b19bb36ULL,
+ 0x008e75ce3d27b1fcULL, 0x00a65daa03b29a27ULL,
+ 0x00d9cc83684eb145ULL, 0x009e1ed80cc2ed74ULL)},
+ {FIELD_LITERAL(0x00bed953d1997988ULL, 0x00b93ed175a24128ULL,
+ 0x00871c5963fb6365ULL, 0x00ca2df20014a787ULL,
+ 0x00f5d9c1d0b34322ULL, 0x00f6f5942818db0aULL,
+ 0x004cc091f49c9906ULL, 0x00e8a188a60bff9fULL)},
}}, {{
- {FIELD_LITERAL(0x0032c7762032fae8,0x00e4087232e0bc21,0x00f767344b6e8d85,0x00bbf369b76c2aa2,0x008a1f46c6e1570c,0x001368cd9780369f,0x007359a39d079430,0x0003646512921434)},
- {FIELD_LITERAL(0x007c4b47ca7c73e7,0x005396221039734b,0x008b64ddf0e45d7e,0x00bfad5af285e6c2,0x008ec711c5b1a1a8,0x00cf663301237f98,0x00917ee3f1655126,0x004152f337efedd8)},
- {FIELD_LITERAL(0x0007c7edc9305daa,0x000a6664f273701c,0x00f6e78795e200b1,0x005d05b9ecd2473e,0x0014f5f17c865786,0x00c7fd2d166fa995,0x004939a2d8eb80e0,0x002244ba0942c199)},
+ {FIELD_LITERAL(0x0032c7762032fae8ULL, 0x00e4087232e0bc21ULL,
+ 0x00f767344b6e8d85ULL, 0x00bbf369b76c2aa2ULL,
+ 0x008a1f46c6e1570cULL, 0x001368cd9780369fULL,
+ 0x007359a39d079430ULL, 0x0003646512921434ULL)},
+ {FIELD_LITERAL(0x007c4b47ca7c73e7ULL, 0x005396221039734bULL,
+ 0x008b64ddf0e45d7eULL, 0x00bfad5af285e6c2ULL,
+ 0x008ec711c5b1a1a8ULL, 0x00cf663301237f98ULL,
+ 0x00917ee3f1655126ULL, 0x004152f337efedd8ULL)},
+ {FIELD_LITERAL(0x0007c7edc9305daaULL, 0x000a6664f273701cULL,
+ 0x00f6e78795e200b1ULL, 0x005d05b9ecd2473eULL,
+ 0x0014f5f17c865786ULL, 0x00c7fd2d166fa995ULL,
+ 0x004939a2d8eb80e0ULL, 0x002244ba0942c199ULL)},
}}, {{
- {FIELD_LITERAL(0x00321e767f0262cf,0x002e57d776caf68e,0x00bf2c94814f0437,0x00c339196acd622f,0x001db4cce71e2770,0x001ded5ddba6eee2,0x0078608ab1554c8d,0x00067fe0ab76365b)},
- {FIELD_LITERAL(0x00f09758e11e3985,0x00169efdbd64fad3,0x00e8889b7d6dacd6,0x0035cdd58ea88209,0x00bcda47586d7f49,0x003cdddcb2879088,0x0016da70187e954b,0x009556ea2e92aacd)},
- {FIELD_LITERAL(0x008cab16bd1ff897,0x00b389972cdf753f,0x00ea8ed1e46dfdc0,0x004fe7ef94c589f4,0x002b8ae9b805ecf3,0x0025c08d892874a5,0x0023938e98d44c4c,0x00f759134cabf69c)},
+ {FIELD_LITERAL(0x00321e767f0262cfULL, 0x002e57d776caf68eULL,
+ 0x00bf2c94814f0437ULL, 0x00c339196acd622fULL,
+ 0x001db4cce71e2770ULL, 0x001ded5ddba6eee2ULL,
+ 0x0078608ab1554c8dULL, 0x00067fe0ab76365bULL)},
+ {FIELD_LITERAL(0x00f09758e11e3985ULL, 0x00169efdbd64fad3ULL,
+ 0x00e8889b7d6dacd6ULL, 0x0035cdd58ea88209ULL,
+ 0x00bcda47586d7f49ULL, 0x003cdddcb2879088ULL,
+ 0x0016da70187e954bULL, 0x009556ea2e92aacdULL)},
+ {FIELD_LITERAL(0x008cab16bd1ff897ULL, 0x00b389972cdf753fULL,
+ 0x00ea8ed1e46dfdc0ULL, 0x004fe7ef94c589f4ULL,
+ 0x002b8ae9b805ecf3ULL, 0x0025c08d892874a5ULL,
+ 0x0023938e98d44c4cULL, 0x00f759134cabf69cULL)},
}}, {{
- {FIELD_LITERAL(0x006c2a84678e4b3b,0x007a194aacd1868f,0x00ed0225af424761,0x00da0a6f293c64b8,0x001062ac5c6a7a18,0x0030f5775a8aeef4,0x0002acaad76b7af0,0x00410b8fd63a579f)},
- {FIELD_LITERAL(0x001ec59db3d9590e,0x001e9e3f1c3f182d,0x0045a9c3ec2cab14,0x0008198572aeb673,0x00773b74068bd167,0x0012535eaa395434,0x0044dba9e3bbb74a,0x002fba4d3c74bd0e)},
- {FIELD_LITERAL(0x0042bf08fe66922c,0x003318b8fbb49e8c,0x00d75946004aa14c,0x00f601586b42bf1c,0x00c74cf1d912fe66,0x00abcb36974b30ad,0x007eb78720c9d2b8,0x009f54ab7bd4df85)},
+ {FIELD_LITERAL(0x006c2a84678e4b3bULL, 0x007a194aacd1868fULL,
+ 0x00ed0225af424761ULL, 0x00da0a6f293c64b8ULL,
+ 0x001062ac5c6a7a18ULL, 0x0030f5775a8aeef4ULL,
+ 0x0002acaad76b7af0ULL, 0x00410b8fd63a579fULL)},
+ {FIELD_LITERAL(0x001ec59db3d9590eULL, 0x001e9e3f1c3f182dULL,
+ 0x0045a9c3ec2cab14ULL, 0x0008198572aeb673ULL,
+ 0x00773b74068bd167ULL, 0x0012535eaa395434ULL,
+ 0x0044dba9e3bbb74aULL, 0x002fba4d3c74bd0eULL)},
+ {FIELD_LITERAL(0x0042bf08fe66922cULL, 0x003318b8fbb49e8cULL,
+ 0x00d75946004aa14cULL, 0x00f601586b42bf1cULL,
+ 0x00c74cf1d912fe66ULL, 0x00abcb36974b30adULL,
+ 0x007eb78720c9d2b8ULL, 0x009f54ab7bd4df85ULL)},
}}, {{
- {FIELD_LITERAL(0x00db9fc948f73826,0x00fa8b3746ed8ee9,0x00132cb65aafbeb2,0x00c36ff3fe7925b8,0x00837daed353d2fe,0x00ec661be0667cf4,0x005beb8ed2e90204,0x00d77dd69e564967)},
- {FIELD_LITERAL(0x0042e6268b861751,0x0008dd0469500c16,0x00b51b57c338a3fd,0x00cc4497d85cff6b,0x002f13d6b57c34a4,0x0083652eaf301105,0x00cc344294cc93a8,0x0060f4d02810e270)},
- {FIELD_LITERAL(0x00a8954363cd518b,0x00ad171124bccb7b,0x0065f46a4adaae00,0x001b1a5b2a96e500,0x0043fe24f8233285,0x0066996d8ae1f2c3,0x00c530f3264169f9,0x00c0f92d07cf6a57)},
+ {FIELD_LITERAL(0x00db9fc948f73826ULL, 0x00fa8b3746ed8ee9ULL,
+ 0x00132cb65aafbeb2ULL, 0x00c36ff3fe7925b8ULL,
+ 0x00837daed353d2feULL, 0x00ec661be0667cf4ULL,
+ 0x005beb8ed2e90204ULL, 0x00d77dd69e564967ULL)},
+ {FIELD_LITERAL(0x0042e6268b861751ULL, 0x0008dd0469500c16ULL,
+ 0x00b51b57c338a3fdULL, 0x00cc4497d85cff6bULL,
+ 0x002f13d6b57c34a4ULL, 0x0083652eaf301105ULL,
+ 0x00cc344294cc93a8ULL, 0x0060f4d02810e270ULL)},
+ {FIELD_LITERAL(0x00a8954363cd518bULL, 0x00ad171124bccb7bULL,
+ 0x0065f46a4adaae00ULL, 0x001b1a5b2a96e500ULL,
+ 0x0043fe24f8233285ULL, 0x0066996d8ae1f2c3ULL,
+ 0x00c530f3264169f9ULL, 0x00c0f92d07cf6a57ULL)},
}}, {{
- {FIELD_LITERAL(0x0036a55c6815d943,0x008c8d1def993db3,0x002e0e1e8ff7318f,0x00d883a4b92db00a,0x002f5e781ae33906,0x001a72adb235c06d,0x00f2e59e736e9caa,0x001a4b58e3031914)},
- {FIELD_LITERAL(0x00d73bfae5e00844,0x00bf459766fb5f52,0x0061b4f5a5313cde,0x004392d4c3b95514,0x000d3551b1077523,0x0000998840ee5d71,0x006de6e340448b7b,0x00251aa504875d6e)},
- {FIELD_LITERAL(0x003bf343427ac342,0x00adc0a78642b8c5,0x0003b893175a8314,0x0061a34ade5703bc,0x00ea3ea8bb71d632,0x00be0df9a1f198c2,0x0046dd8e7c1635fb,0x00f1523fdd25d5e5)},
+ {FIELD_LITERAL(0x0036a55c6815d943ULL, 0x008c8d1def993db3ULL,
+ 0x002e0e1e8ff7318fULL, 0x00d883a4b92db00aULL,
+ 0x002f5e781ae33906ULL, 0x001a72adb235c06dULL,
+ 0x00f2e59e736e9caaULL, 0x001a4b58e3031914ULL)},
+ {FIELD_LITERAL(0x00d73bfae5e00844ULL, 0x00bf459766fb5f52ULL,
+ 0x0061b4f5a5313cdeULL, 0x004392d4c3b95514ULL,
+ 0x000d3551b1077523ULL, 0x0000998840ee5d71ULL,
+ 0x006de6e340448b7bULL, 0x00251aa504875d6eULL)},
+ {FIELD_LITERAL(0x003bf343427ac342ULL, 0x00adc0a78642b8c5ULL,
+ 0x0003b893175a8314ULL, 0x0061a34ade5703bcULL,
+ 0x00ea3ea8bb71d632ULL, 0x00be0df9a1f198c2ULL,
+ 0x0046dd8e7c1635fbULL, 0x00f1523fdd25d5e5ULL)},
}}, {{
- {FIELD_LITERAL(0x00633f63fc9dd406,0x00e713ff80e04a43,0x0060c6e970f2d621,0x00a57cd7f0df1891,0x00f2406a550650bb,0x00b064290efdc684,0x001eab0144d17916,0x00cd15f863c293ab)},
- {FIELD_LITERAL(0x0029cec55273f70d,0x007044ee275c6340,0x0040f637a93015e2,0x00338bb78db5aae9,0x001491b2a6132147,0x00a125d6cfe6bde3,0x005f7ac561ba8669,0x001d5eaea3fbaacf)},
- {FIELD_LITERAL(0x00054e9635e3be31,0x000e43f31e2872be,0x00d05b1c9e339841,0x006fac50bd81fd98,0x00cdc7852eaebb09,0x004ff519b061991b,0x009099e8107d4c85,0x00273e24c36a4a61)},
+ {FIELD_LITERAL(0x00633f63fc9dd406ULL, 0x00e713ff80e04a43ULL,
+ 0x0060c6e970f2d621ULL, 0x00a57cd7f0df1891ULL,
+ 0x00f2406a550650bbULL, 0x00b064290efdc684ULL,
+ 0x001eab0144d17916ULL, 0x00cd15f863c293abULL)},
+ {FIELD_LITERAL(0x0029cec55273f70dULL, 0x007044ee275c6340ULL,
+ 0x0040f637a93015e2ULL, 0x00338bb78db5aae9ULL,
+ 0x001491b2a6132147ULL, 0x00a125d6cfe6bde3ULL,
+ 0x005f7ac561ba8669ULL, 0x001d5eaea3fbaacfULL)},
+ {FIELD_LITERAL(0x00054e9635e3be31ULL, 0x000e43f31e2872beULL,
+ 0x00d05b1c9e339841ULL, 0x006fac50bd81fd98ULL,
+ 0x00cdc7852eaebb09ULL, 0x004ff519b061991bULL,
+ 0x009099e8107d4c85ULL, 0x00273e24c36a4a61ULL)},
}}, {{
- {FIELD_LITERAL(0x00070b4441ef2c46,0x00efa5b02801a109,0x00bf0b8c3ee64adf,0x008a67e0b3452e98,0x001916b1f2fa7a74,0x00d781a78ff6cdc3,0x008682ce57e5c919,0x00cc1109dd210da3)},
- {FIELD_LITERAL(0x00cae8aaff388663,0x005e983a35dda1c7,0x007ab1030d8e37f4,0x00e48940f5d032fe,0x006a36f9ef30b331,0x009be6f03958c757,0x0086231ceba91400,0x008bd0f7b823e7aa)},
- {FIELD_LITERAL(0x00cf881ebef5a45a,0x004ebea78e7c6f2c,0x0090da9209cf26a0,0x00de2b2e4c775b84,0x0071d6031c3c15ae,0x00d9e927ef177d70,0x00894ee8c23896fd,0x00e3b3b401e41aad)},
+ {FIELD_LITERAL(0x00070b4441ef2c46ULL, 0x00efa5b02801a109ULL,
+ 0x00bf0b8c3ee64adfULL, 0x008a67e0b3452e98ULL,
+ 0x001916b1f2fa7a74ULL, 0x00d781a78ff6cdc3ULL,
+ 0x008682ce57e5c919ULL, 0x00cc1109dd210da3ULL)},
+ {FIELD_LITERAL(0x00cae8aaff388663ULL, 0x005e983a35dda1c7ULL,
+ 0x007ab1030d8e37f4ULL, 0x00e48940f5d032feULL,
+ 0x006a36f9ef30b331ULL, 0x009be6f03958c757ULL,
+ 0x0086231ceba91400ULL, 0x008bd0f7b823e7aaULL)},
+ {FIELD_LITERAL(0x00cf881ebef5a45aULL, 0x004ebea78e7c6f2cULL,
+ 0x0090da9209cf26a0ULL, 0x00de2b2e4c775b84ULL,
+ 0x0071d6031c3c15aeULL, 0x00d9e927ef177d70ULL,
+ 0x00894ee8c23896fdULL, 0x00e3b3b401e41aadULL)},
}}, {{
- {FIELD_LITERAL(0x00204fef26864170,0x00819269c5dee0f8,0x00bfb4713ec97966,0x0026339a6f34df78,0x001f26e64c761dc2,0x00effe3af313cb60,0x00e17b70138f601b,0x00f16e1ccd9ede5e)},
- {FIELD_LITERAL(0x005d9a8353fdb2db,0x0055cc2048c698f0,0x00f6c4ac89657218,0x00525034d73faeb2,0x00435776fbda3c7d,0x0070ea5312323cbc,0x007a105d44d069fb,0x006dbc8d6dc786aa)},
- {FIELD_LITERAL(0x0017cff19cd394ec,0x00fef7b810922587,0x00e6483970dff548,0x00ddf36ad6874264,0x00e61778523fcce2,0x0093a66c0c93b24a,0x00fd367114db7f86,0x007652d7ddce26dd)},
+ {FIELD_LITERAL(0x00204fef26864170ULL, 0x00819269c5dee0f8ULL,
+ 0x00bfb4713ec97966ULL, 0x0026339a6f34df78ULL,
+ 0x001f26e64c761dc2ULL, 0x00effe3af313cb60ULL,
+ 0x00e17b70138f601bULL, 0x00f16e1ccd9ede5eULL)},
+ {FIELD_LITERAL(0x005d9a8353fdb2dbULL, 0x0055cc2048c698f0ULL,
+ 0x00f6c4ac89657218ULL, 0x00525034d73faeb2ULL,
+ 0x00435776fbda3c7dULL, 0x0070ea5312323cbcULL,
+ 0x007a105d44d069fbULL, 0x006dbc8d6dc786aaULL)},
+ {FIELD_LITERAL(0x0017cff19cd394ecULL, 0x00fef7b810922587ULL,
+ 0x00e6483970dff548ULL, 0x00ddf36ad6874264ULL,
+ 0x00e61778523fcce2ULL, 0x0093a66c0c93b24aULL,
+ 0x00fd367114db7f86ULL, 0x007652d7ddce26ddULL)},
}}, {{
- {FIELD_LITERAL(0x00d92ced7ba12843,0x00aea9c7771e86e7,0x0046639693354f7b,0x00a628dbb6a80c47,0x003a0b0507372953,0x00421113ab45c0d9,0x00e545f08362ab7a,0x0028ce087b4d6d96)},
- {FIELD_LITERAL(0x00a67ee7cf9f99eb,0x005713b275f2ff68,0x00f1d536a841513d,0x00823b59b024712e,0x009c46b9d0d38cec,0x00cdb1595aa2d7d4,0x008375b3423d9af8,0x000ab0b516d978f7)},
- {FIELD_LITERAL(0x00428dcb3c510b0f,0x00585607ea24bb4e,0x003736bf1603687a,0x00c47e568c4fe3c7,0x003cd00282848605,0x0043a487c3b91939,0x004ffc04e1095a06,0x00a4c989a3d4b918)},
+ {FIELD_LITERAL(0x00d92ced7ba12843ULL, 0x00aea9c7771e86e7ULL,
+ 0x0046639693354f7bULL, 0x00a628dbb6a80c47ULL,
+ 0x003a0b0507372953ULL, 0x00421113ab45c0d9ULL,
+ 0x00e545f08362ab7aULL, 0x0028ce087b4d6d96ULL)},
+ {FIELD_LITERAL(0x00a67ee7cf9f99ebULL, 0x005713b275f2ff68ULL,
+ 0x00f1d536a841513dULL, 0x00823b59b024712eULL,
+ 0x009c46b9d0d38cecULL, 0x00cdb1595aa2d7d4ULL,
+ 0x008375b3423d9af8ULL, 0x000ab0b516d978f7ULL)},
+ {FIELD_LITERAL(0x00428dcb3c510b0fULL, 0x00585607ea24bb4eULL,
+ 0x003736bf1603687aULL, 0x00c47e568c4fe3c7ULL,
+ 0x003cd00282848605ULL, 0x0043a487c3b91939ULL,
+ 0x004ffc04e1095a06ULL, 0x00a4c989a3d4b918ULL)},
}}, {{
- {FIELD_LITERAL(0x00a8778d0e429f7a,0x004c02b059105a68,0x0016653b609da3ff,0x00d5107bd1a12d27,0x00b4708f9a771cab,0x00bb63b662033f69,0x0072f322240e7215,0x0019445b59c69222)},
- {FIELD_LITERAL(0x00cf4f6069a658e6,0x0053ca52859436a6,0x0064b994d7e3e117,0x00cb469b9a07f534,0x00cfb68f399e9d47,0x00f0dcb8dac1c6e7,0x00f2ab67f538b3a5,0x0055544f178ab975)},
- {FIELD_LITERAL(0x0099b7a2685d538c,0x00e2f1897b7c0018,0x003adac8ce48dae3,0x00089276d5c50c0c,0x00172fca07ad6717,0x00cb1a72f54069e5,0x004ee42f133545b3,0x00785f8651362f16)},
+ {FIELD_LITERAL(0x00a8778d0e429f7aULL, 0x004c02b059105a68ULL,
+ 0x0016653b609da3ffULL, 0x00d5107bd1a12d27ULL,
+ 0x00b4708f9a771cabULL, 0x00bb63b662033f69ULL,
+ 0x0072f322240e7215ULL, 0x0019445b59c69222ULL)},
+ {FIELD_LITERAL(0x00cf4f6069a658e6ULL, 0x0053ca52859436a6ULL,
+ 0x0064b994d7e3e117ULL, 0x00cb469b9a07f534ULL,
+ 0x00cfb68f399e9d47ULL, 0x00f0dcb8dac1c6e7ULL,
+ 0x00f2ab67f538b3a5ULL, 0x0055544f178ab975ULL)},
+ {FIELD_LITERAL(0x0099b7a2685d538cULL, 0x00e2f1897b7c0018ULL,
+ 0x003adac8ce48dae3ULL, 0x00089276d5c50c0cULL,
+ 0x00172fca07ad6717ULL, 0x00cb1a72f54069e5ULL,
+ 0x004ee42f133545b3ULL, 0x00785f8651362f16ULL)},
}}, {{
- {FIELD_LITERAL(0x0049cbac38509e11,0x0015234505d42cdf,0x00794fb0b5840f1c,0x00496437344045a5,0x0031b6d944e4f9b0,0x00b207318ac1f5d8,0x0000c840da7f5c5d,0x00526f373a5c8814)},
- {FIELD_LITERAL(0x002c7b7742d1dfd9,0x002cabeb18623c01,0x00055f5e3e044446,0x006c20f3b4ef54ba,0x00c600141ec6b35f,0x00354f437f1a32a3,0x00bac4624a3520f9,0x00c483f734a90691)},
- {FIELD_LITERAL(0x0053a737d422918d,0x00f7fca1d8758625,0x00c360336dadb04c,0x00f38e3d9158a1b8,0x0069ce3b418e84c6,0x005d1697eca16ead,0x00f8bd6a35ece13d,0x007885dfc2b5afea)},
+ {FIELD_LITERAL(0x0049cbac38509e11ULL, 0x0015234505d42cdfULL,
+ 0x00794fb0b5840f1cULL, 0x00496437344045a5ULL,
+ 0x0031b6d944e4f9b0ULL, 0x00b207318ac1f5d8ULL,
+ 0x0000c840da7f5c5dULL, 0x00526f373a5c8814ULL)},
+ {FIELD_LITERAL(0x002c7b7742d1dfd9ULL, 0x002cabeb18623c01ULL,
+ 0x00055f5e3e044446ULL, 0x006c20f3b4ef54baULL,
+ 0x00c600141ec6b35fULL, 0x00354f437f1a32a3ULL,
+ 0x00bac4624a3520f9ULL, 0x00c483f734a90691ULL)},
+ {FIELD_LITERAL(0x0053a737d422918dULL, 0x00f7fca1d8758625ULL,
+ 0x00c360336dadb04cULL, 0x00f38e3d9158a1b8ULL,
+ 0x0069ce3b418e84c6ULL, 0x005d1697eca16eadULL,
+ 0x00f8bd6a35ece13dULL, 0x007885dfc2b5afeaULL)},
}}, {{
- {FIELD_LITERAL(0x00c3617ae260776c,0x00b20dc3e96922d7,0x00a1a7802246706a,0x00ca6505a5240244,0x002246b62d919782,0x001439102d7aa9b3,0x00e8af1139e6422c,0x00c888d1b52f2b05)},
- {FIELD_LITERAL(0x005b67690ffd41d9,0x005294f28df516f9,0x00a879272412fcb9,0x00098b629a6d1c8d,0x00fabd3c8050865a,0x00cd7e5b0a3879c5,0x00153238210f3423,0x00357cac101e9f42)},
- {FIELD_LITERAL(0x008917b454444fb7,0x00f59247c97e441b,0x00a6200a6815152d,0x0009a4228601d254,0x001c0360559bd374,0x007563362039cb36,0x00bd75b48d74e32b,0x0017f515ac3499e8)},
+ {FIELD_LITERAL(0x00c3617ae260776cULL, 0x00b20dc3e96922d7ULL,
+ 0x00a1a7802246706aULL, 0x00ca6505a5240244ULL,
+ 0x002246b62d919782ULL, 0x001439102d7aa9b3ULL,
+ 0x00e8af1139e6422cULL, 0x00c888d1b52f2b05ULL)},
+ {FIELD_LITERAL(0x005b67690ffd41d9ULL, 0x005294f28df516f9ULL,
+ 0x00a879272412fcb9ULL, 0x00098b629a6d1c8dULL,
+ 0x00fabd3c8050865aULL, 0x00cd7e5b0a3879c5ULL,
+ 0x00153238210f3423ULL, 0x00357cac101e9f42ULL)},
+ {FIELD_LITERAL(0x008917b454444fb7ULL, 0x00f59247c97e441bULL,
+ 0x00a6200a6815152dULL, 0x0009a4228601d254ULL,
+ 0x001c0360559bd374ULL, 0x007563362039cb36ULL,
+ 0x00bd75b48d74e32bULL, 0x0017f515ac3499e8ULL)},
}}, {{
- {FIELD_LITERAL(0x001532a7ffe41c5a,0x00eb1edce358d6bf,0x00ddbacc7b678a7b,0x008a7b70f3c841a3,0x00f1923bf27d3f4c,0x000b2713ed8f7873,0x00aaf67e29047902,0x0044994a70b3976d)},
- {FIELD_LITERAL(0x00d54e802082d42c,0x00a55aa0dce7cc6c,0x006477b96073f146,0x0082efe4ceb43594,0x00a922bcba026845,0x0077f19d1ab75182,0x00c2bb2737846e59,0x0004d7eec791dd33)},
- {FIELD_LITERAL(0x0044588d1a81d680,0x00b0a9097208e4f8,0x00212605350dc57e,0x0028717cd2871123,0x00fb083c100fd979,0x0045a056ce063fdf,0x00a5d604b4dd6a41,0x001dabc08ba4e236)},
+ {FIELD_LITERAL(0x001532a7ffe41c5aULL, 0x00eb1edce358d6bfULL,
+ 0x00ddbacc7b678a7bULL, 0x008a7b70f3c841a3ULL,
+ 0x00f1923bf27d3f4cULL, 0x000b2713ed8f7873ULL,
+ 0x00aaf67e29047902ULL, 0x0044994a70b3976dULL)},
+ {FIELD_LITERAL(0x00d54e802082d42cULL, 0x00a55aa0dce7cc6cULL,
+ 0x006477b96073f146ULL, 0x0082efe4ceb43594ULL,
+ 0x00a922bcba026845ULL, 0x0077f19d1ab75182ULL,
+ 0x00c2bb2737846e59ULL, 0x0004d7eec791dd33ULL)},
+ {FIELD_LITERAL(0x0044588d1a81d680ULL, 0x00b0a9097208e4f8ULL,
+ 0x00212605350dc57eULL, 0x0028717cd2871123ULL,
+ 0x00fb083c100fd979ULL, 0x0045a056ce063fdfULL,
+ 0x00a5d604b4dd6a41ULL, 0x001dabc08ba4e236ULL)},
}}, {{
- {FIELD_LITERAL(0x00c4887198d7a7fa,0x00244f98fb45784a,0x0045911e15a15d01,0x001d323d374c0966,0x00967c3915196562,0x0039373abd2f3c67,0x000d2c5614312423,0x0041cf2215442ce3)},
- {FIELD_LITERAL(0x008ede889ada7f06,0x001611e91de2e135,0x00fdb9a458a471b9,0x00563484e03710d1,0x0031cc81925e3070,0x0062c97b3af80005,0x00fa733eea28edeb,0x00e82457e1ebbc88)},
- {FIELD_LITERAL(0x006a0df5fe9b6f59,0x00a0d4ff46040d92,0x004a7cedb6f93250,0x00d1df8855b8c357,0x00e73a46086fd058,0x0048fb0add6dfe59,0x001e03a28f1b4e3d,0x00a871c993308d76)},
+ {FIELD_LITERAL(0x00c4887198d7a7faULL, 0x00244f98fb45784aULL,
+ 0x0045911e15a15d01ULL, 0x001d323d374c0966ULL,
+ 0x00967c3915196562ULL, 0x0039373abd2f3c67ULL,
+ 0x000d2c5614312423ULL, 0x0041cf2215442ce3ULL)},
+ {FIELD_LITERAL(0x008ede889ada7f06ULL, 0x001611e91de2e135ULL,
+ 0x00fdb9a458a471b9ULL, 0x00563484e03710d1ULL,
+ 0x0031cc81925e3070ULL, 0x0062c97b3af80005ULL,
+ 0x00fa733eea28edebULL, 0x00e82457e1ebbc88ULL)},
+ {FIELD_LITERAL(0x006a0df5fe9b6f59ULL, 0x00a0d4ff46040d92ULL,
+ 0x004a7cedb6f93250ULL, 0x00d1df8855b8c357ULL,
+ 0x00e73a46086fd058ULL, 0x0048fb0add6dfe59ULL,
+ 0x001e03a28f1b4e3dULL, 0x00a871c993308d76ULL)},
}}, {{
- {FIELD_LITERAL(0x0030dbb2d1766ec8,0x00586c0ad138555e,0x00d1a34f9e91c77c,0x0063408ad0e89014,0x00d61231b05f6f5b,0x0009abf569f5fd8a,0x00aec67a110f1c43,0x0031d1a790938dd7)},
- {FIELD_LITERAL(0x006cded841e2a862,0x00198d60af0ab6fb,0x0018f09db809e750,0x004e6ac676016263,0x00eafcd1620969cb,0x002c9784ca34917d,0x0054f00079796de7,0x00d9fab5c5972204)},
- {FIELD_LITERAL(0x004bd0fee2438a83,0x00b571e62b0f83bd,0x0059287d7ce74800,0x00fb3631b645c3f0,0x00a018e977f78494,0x0091e27065c27b12,0x007696c1817165e0,0x008c40be7c45ba3a)},
+ {FIELD_LITERAL(0x0030dbb2d1766ec8ULL, 0x00586c0ad138555eULL,
+ 0x00d1a34f9e91c77cULL, 0x0063408ad0e89014ULL,
+ 0x00d61231b05f6f5bULL, 0x0009abf569f5fd8aULL,
+ 0x00aec67a110f1c43ULL, 0x0031d1a790938dd7ULL)},
+ {FIELD_LITERAL(0x006cded841e2a862ULL, 0x00198d60af0ab6fbULL,
+ 0x0018f09db809e750ULL, 0x004e6ac676016263ULL,
+ 0x00eafcd1620969cbULL, 0x002c9784ca34917dULL,
+ 0x0054f00079796de7ULL, 0x00d9fab5c5972204ULL)},
+ {FIELD_LITERAL(0x004bd0fee2438a83ULL, 0x00b571e62b0f83bdULL,
+ 0x0059287d7ce74800ULL, 0x00fb3631b645c3f0ULL,
+ 0x00a018e977f78494ULL, 0x0091e27065c27b12ULL,
+ 0x007696c1817165e0ULL, 0x008c40be7c45ba3aULL)},
}}, {{
- {FIELD_LITERAL(0x00a0f326327cb684,0x001c7d0f672680ff,0x008c1c81ffb112d1,0x00f8f801674eddc8,0x00e926d5d48c2a9d,0x005bd6d954c6fe9a,0x004c6b24b4e33703,0x00d05eb5c09105cc)},
- {FIELD_LITERAL(0x00d61731caacf2cf,0x002df0c7609e01c5,0x00306172208b1e2b,0x00b413fe4fb2b686,0x00826d360902a221,0x003f8d056e67e7f7,0x0065025b0175e989,0x00369add117865eb)},
- {FIELD_LITERAL(0x00aaf895aec2fa11,0x000f892bc313eb52,0x005b1c794dad050b,0x003f8ec4864cec14,0x00af81058d0b90e5,0x00ebe43e183997bb,0x00a9d610f9f3e615,0x007acd8eec2e88d3)},
+ {FIELD_LITERAL(0x00a0f326327cb684ULL, 0x001c7d0f672680ffULL,
+ 0x008c1c81ffb112d1ULL, 0x00f8f801674eddc8ULL,
+ 0x00e926d5d48c2a9dULL, 0x005bd6d954c6fe9aULL,
+ 0x004c6b24b4e33703ULL, 0x00d05eb5c09105ccULL)},
+ {FIELD_LITERAL(0x00d61731caacf2cfULL, 0x002df0c7609e01c5ULL,
+ 0x00306172208b1e2bULL, 0x00b413fe4fb2b686ULL,
+ 0x00826d360902a221ULL, 0x003f8d056e67e7f7ULL,
+ 0x0065025b0175e989ULL, 0x00369add117865ebULL)},
+ {FIELD_LITERAL(0x00aaf895aec2fa11ULL, 0x000f892bc313eb52ULL,
+ 0x005b1c794dad050bULL, 0x003f8ec4864cec14ULL,
+ 0x00af81058d0b90e5ULL, 0x00ebe43e183997bbULL,
+ 0x00a9d610f9f3e615ULL, 0x007acd8eec2e88d3ULL)},
}}, {{
- {FIELD_LITERAL(0x0049b2fab13812a3,0x00846db32cd60431,0x000177fa578c8d6c,0x00047d0e2ad4bc51,0x00b158ba38d1e588,0x006a45daad79e3f3,0x000997b93cab887b,0x00c47ea42fa23dc3)},
- {FIELD_LITERAL(0x0012b6fef7aeb1ca,0x009412768194b6a7,0x00ff0d351f23ab93,0x007e8a14c1aff71b,0x006c1c0170c512bc,0x0016243ea02ab2e5,0x007bb6865b303f3e,0x0015ce6b29b159f4)},
- {FIELD_LITERAL(0x009961cd02e68108,0x00e2035d3a1d0836,0x005d51f69b5e1a1d,0x004bccb4ea36edcd,0x0069be6a7aeef268,0x0063f4dd9de8d5a7,0x006283783092ca35,0x0075a31af2c35409)},
+ {FIELD_LITERAL(0x0049b2fab13812a3ULL, 0x00846db32cd60431ULL,
+ 0x000177fa578c8d6cULL, 0x00047d0e2ad4bc51ULL,
+ 0x00b158ba38d1e588ULL, 0x006a45daad79e3f3ULL,
+ 0x000997b93cab887bULL, 0x00c47ea42fa23dc3ULL)},
+ {FIELD_LITERAL(0x0012b6fef7aeb1caULL, 0x009412768194b6a7ULL,
+ 0x00ff0d351f23ab93ULL, 0x007e8a14c1aff71bULL,
+ 0x006c1c0170c512bcULL, 0x0016243ea02ab2e5ULL,
+ 0x007bb6865b303f3eULL, 0x0015ce6b29b159f4ULL)},
+ {FIELD_LITERAL(0x009961cd02e68108ULL, 0x00e2035d3a1d0836ULL,
+ 0x005d51f69b5e1a1dULL, 0x004bccb4ea36edcdULL,
+ 0x0069be6a7aeef268ULL, 0x0063f4dd9de8d5a7ULL,
+ 0x006283783092ca35ULL, 0x0075a31af2c35409ULL)},
}}, {{
- {FIELD_LITERAL(0x00c412365162e8cf,0x00012283fb34388a,0x003e6543babf39e2,0x00eead6b3a804978,0x0099c0314e8b326f,0x00e98e0a8d477a4f,0x00d2eb96b127a687,0x00ed8d7df87571bb)},
- {FIELD_LITERAL(0x00777463e308cacf,0x00c8acb93950132d,0x00ebddbf4ca48b2c,0x0026ad7ca0795a0a,0x00f99a3d9a715064,0x000d60bcf9d4dfcc,0x005e65a73a437a06,0x0019d536a8db56c8)},
- {FIELD_LITERAL(0x00192d7dd558d135,0x0027cd6a8323ffa7,0x00239f1a412dc1e7,0x0046b4b3be74fc5c,0x0020c47a2bef5bce,0x00aa17e48f43862b,0x00f7e26c96342e5f,0x0008011c530f39a9)},
+ {FIELD_LITERAL(0x00c412365162e8cfULL, 0x00012283fb34388aULL,
+ 0x003e6543babf39e2ULL, 0x00eead6b3a804978ULL,
+ 0x0099c0314e8b326fULL, 0x00e98e0a8d477a4fULL,
+ 0x00d2eb96b127a687ULL, 0x00ed8d7df87571bbULL)},
+ {FIELD_LITERAL(0x00777463e308cacfULL, 0x00c8acb93950132dULL,
+ 0x00ebddbf4ca48b2cULL, 0x0026ad7ca0795a0aULL,
+ 0x00f99a3d9a715064ULL, 0x000d60bcf9d4dfccULL,
+ 0x005e65a73a437a06ULL, 0x0019d536a8db56c8ULL)},
+ {FIELD_LITERAL(0x00192d7dd558d135ULL, 0x0027cd6a8323ffa7ULL,
+ 0x00239f1a412dc1e7ULL, 0x0046b4b3be74fc5cULL,
+ 0x0020c47a2bef5bceULL, 0x00aa17e48f43862bULL,
+ 0x00f7e26c96342e5fULL, 0x0008011c530f39a9ULL)},
}}, {{
- {FIELD_LITERAL(0x00aad4ac569bf0f1,0x00a67adc90b27740,0x0048551369a5751a,0x0031252584a3306a,0x0084e15df770e6fc,0x00d7bba1c74b5805,0x00a80ef223af1012,0x0089c85ceb843a34)},
- {FIELD_LITERAL(0x00c4545be4a54004,0x0099e11f60357e6c,0x001f3936d19515a6,0x007793df84341a6e,0x0051061886717ffa,0x00e9b0a660b28f85,0x0044ea685892de0d,0x000257d2a1fda9d9)},
- {FIELD_LITERAL(0x007e8b01b24ac8a8,0x006cf3b0b5ca1337,0x00f1607d3e36a570,0x0039b7fab82991a1,0x00231777065840c5,0x00998e5afdd346f9,0x00b7dc3e64acc85f,0x00baacc748013ad6)},
+ {FIELD_LITERAL(0x00aad4ac569bf0f1ULL, 0x00a67adc90b27740ULL,
+ 0x0048551369a5751aULL, 0x0031252584a3306aULL,
+ 0x0084e15df770e6fcULL, 0x00d7bba1c74b5805ULL,
+ 0x00a80ef223af1012ULL, 0x0089c85ceb843a34ULL)},
+ {FIELD_LITERAL(0x00c4545be4a54004ULL, 0x0099e11f60357e6cULL,
+ 0x001f3936d19515a6ULL, 0x007793df84341a6eULL,
+ 0x0051061886717ffaULL, 0x00e9b0a660b28f85ULL,
+ 0x0044ea685892de0dULL, 0x000257d2a1fda9d9ULL)},
+ {FIELD_LITERAL(0x007e8b01b24ac8a8ULL, 0x006cf3b0b5ca1337ULL,
+ 0x00f1607d3e36a570ULL, 0x0039b7fab82991a1ULL,
+ 0x00231777065840c5ULL, 0x00998e5afdd346f9ULL,
+ 0x00b7dc3e64acc85fULL, 0x00baacc748013ad6ULL)},
}}, {{
- {FIELD_LITERAL(0x008ea6a4177580bf,0x005fa1953e3f0378,0x005fe409ac74d614,0x00452327f477e047,0x00a4018507fb6073,0x007b6e71951caac8,0x0012b42ab8a6ce91,0x0080eca677294ab7)},
- {FIELD_LITERAL(0x00a53edc023ba69b,0x00c6afa83ddde2e8,0x00c3f638b307b14e,0x004a357a64414062,0x00e4d94d8b582dc9,0x001739caf71695b7,0x0012431b2ae28de1,0x003b6bc98682907c)},
- {FIELD_LITERAL(0x008a9a93be1f99d6,0x0079fa627cc699c8,0x00b0cfb134ba84c8,0x001c4b778249419a,0x00df4ab3d9c44f40,0x009f596e6c1a9e3c,0x001979c0df237316,0x00501e953a919b87)},
+ {FIELD_LITERAL(0x008ea6a4177580bfULL, 0x005fa1953e3f0378ULL,
+ 0x005fe409ac74d614ULL, 0x00452327f477e047ULL,
+ 0x00a4018507fb6073ULL, 0x007b6e71951caac8ULL,
+ 0x0012b42ab8a6ce91ULL, 0x0080eca677294ab7ULL)},
+ {FIELD_LITERAL(0x00a53edc023ba69bULL, 0x00c6afa83ddde2e8ULL,
+ 0x00c3f638b307b14eULL, 0x004a357a64414062ULL,
+ 0x00e4d94d8b582dc9ULL, 0x001739caf71695b7ULL,
+ 0x0012431b2ae28de1ULL, 0x003b6bc98682907cULL)},
+ {FIELD_LITERAL(0x008a9a93be1f99d6ULL, 0x0079fa627cc699c8ULL,
+ 0x00b0cfb134ba84c8ULL, 0x001c4b778249419aULL,
+ 0x00df4ab3d9c44f40ULL, 0x009f596e6c1a9e3cULL,
+ 0x001979c0df237316ULL, 0x00501e953a919b87ULL)},
}}
};
const niels_t *curve448_wnaf_base = curve448_wnaf_base_table;
diff --git a/freebsd/crypto/openssl/crypto/ec/curve448/curve448utils.h b/freebsd/crypto/openssl/crypto/ec/curve448/curve448utils.h
index 9bf83799..9032bb4f 100644
--- a/freebsd/crypto/openssl/crypto/ec/curve448/curve448utils.h
+++ b/freebsd/crypto/openssl/crypto/ec/curve448/curve448utils.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2015 Cryptography Research, Inc.
*
* Licensed under the OpenSSL license (the "License"). You may not use
@@ -24,7 +24,9 @@
*/
# ifndef C448_WORD_BITS
# if (defined(__SIZEOF_INT128__) && (__SIZEOF_INT128__ == 16)) \
- && !defined(__sparc__)
+ && !defined(__sparc__) \
+ && (!defined(__SIZEOF_LONG__) || (__SIZEOF_LONG__ == 8))
+
# define C448_WORD_BITS 64 /* The number of bits in a word */
# else
# define C448_WORD_BITS 32 /* The number of bits in a word */
diff --git a/freebsd/crypto/openssl/crypto/ec/curve448/f_generic.c b/freebsd/crypto/openssl/crypto/ec/curve448/f_generic.c
index c505543c..f357dc2a 100644
--- a/freebsd/crypto/openssl/crypto/ec/curve448/f_generic.c
+++ b/freebsd/crypto/openssl/crypto/ec/curve448/f_generic.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2015-2016 Cryptography Research, Inc.
*
* Licensed under the OpenSSL license (the "License"). You may not use
@@ -14,9 +14,9 @@
#include "field.h"
static const gf MODULUS = {
- FIELD_LITERAL(0xffffffffffffff, 0xffffffffffffff, 0xffffffffffffff,
- 0xffffffffffffff, 0xfffffffffffffe, 0xffffffffffffff,
- 0xffffffffffffff, 0xffffffffffffff)
+ FIELD_LITERAL(0xffffffffffffffULL, 0xffffffffffffffULL, 0xffffffffffffffULL,
+ 0xffffffffffffffULL, 0xfffffffffffffeULL, 0xffffffffffffffULL,
+ 0xffffffffffffffULL, 0xffffffffffffffULL)
};
/* Serialize to wire format. */
diff --git a/freebsd/crypto/openssl/crypto/ec/curve448/scalar.c b/freebsd/crypto/openssl/crypto/ec/curve448/scalar.c
index efde5a99..df50a30c 100644
--- a/freebsd/crypto/openssl/crypto/ec/curve448/scalar.c
+++ b/freebsd/crypto/openssl/crypto/ec/curve448/scalar.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2015-2016 Cryptography Research, Inc.
*
* Licensed under the OpenSSL license (the "License"). You may not use
@@ -16,24 +16,24 @@
#include "word.h"
#include "point_448.h"
-static const c448_word_t MONTGOMERY_FACTOR = (c448_word_t) 0x3bd440fae918bc5;
+static const c448_word_t MONTGOMERY_FACTOR = (c448_word_t) 0x3bd440fae918bc5ULL;
static const curve448_scalar_t sc_p = {
{
{
- SC_LIMB(0x2378c292ab5844f3), SC_LIMB(0x216cc2728dc58f55),
- SC_LIMB(0xc44edb49aed63690), SC_LIMB(0xffffffff7cca23e9),
- SC_LIMB(0xffffffffffffffff), SC_LIMB(0xffffffffffffffff),
- SC_LIMB(0x3fffffffffffffff)
+ SC_LIMB(0x2378c292ab5844f3ULL), SC_LIMB(0x216cc2728dc58f55ULL),
+ SC_LIMB(0xc44edb49aed63690ULL), SC_LIMB(0xffffffff7cca23e9ULL),
+ SC_LIMB(0xffffffffffffffffULL), SC_LIMB(0xffffffffffffffffULL),
+ SC_LIMB(0x3fffffffffffffffULL)
}
}
}, sc_r2 = {
{
{
- SC_LIMB(0xe3539257049b9b60), SC_LIMB(0x7af32c4bc1b195d9),
- SC_LIMB(0x0d66de2388ea1859), SC_LIMB(0xae17cf725ee4d838),
- SC_LIMB(0x1a9cc14ba3c47c44), SC_LIMB(0x2052bcb7e4d070af),
- SC_LIMB(0x3402a939f823b729)
+ SC_LIMB(0xe3539257049b9b60ULL), SC_LIMB(0x7af32c4bc1b195d9ULL),
+ SC_LIMB(0x0d66de2388ea1859ULL), SC_LIMB(0xae17cf725ee4d838ULL),
+ SC_LIMB(0x1a9cc14ba3c47c44ULL), SC_LIMB(0x2052bcb7e4d070afULL),
+ SC_LIMB(0x3402a939f823b729ULL)
}
}
};
diff --git a/freebsd/crypto/openssl/crypto/ec/ec2_oct.c b/freebsd/crypto/openssl/crypto/ec/ec2_oct.c
index fe0f9eb2..4dc5ede8 100644
--- a/freebsd/crypto/openssl/crypto/ec/ec2_oct.c
+++ b/freebsd/crypto/openssl/crypto/ec/ec2_oct.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2011-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
* Licensed under the OpenSSL license (the "License"). You may not use
@@ -239,7 +239,7 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
BN_CTX *ctx)
{
point_conversion_form_t form;
- int y_bit;
+ int y_bit, m;
BN_CTX *new_ctx = NULL;
BIGNUM *x, *y, *yxi;
size_t field_len, enc_len;
@@ -272,7 +272,8 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
return EC_POINT_set_to_infinity(group, point);
}
- field_len = (EC_GROUP_get_degree(group) + 7) / 8;
+ m = EC_GROUP_get_degree(group);
+ field_len = (m + 7) / 8;
enc_len =
(form ==
POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len;
@@ -297,7 +298,7 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
if (!BN_bin2bn(buf + 1, field_len, x))
goto err;
- if (BN_ucmp(x, group->field) >= 0) {
+ if (BN_num_bits(x) > m) {
ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
goto err;
}
@@ -308,7 +309,7 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
} else {
if (!BN_bin2bn(buf + 1 + field_len, field_len, y))
goto err;
- if (BN_ucmp(y, group->field) >= 0) {
+ if (BN_num_bits(y) > m) {
ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
goto err;
}
diff --git a/freebsd/crypto/openssl/crypto/ec/ec2_smpl.c b/freebsd/crypto/openssl/crypto/ec/ec2_smpl.c
index af351a80..9003f42d 100644
--- a/freebsd/crypto/openssl/crypto/ec/ec2_smpl.c
+++ b/freebsd/crypto/openssl/crypto/ec/ec2_smpl.c
@@ -206,8 +206,7 @@ int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group,
ret = 1;
err:
- if (ctx != NULL)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
}
diff --git a/freebsd/crypto/openssl/crypto/ec/ec_ameth.c b/freebsd/crypto/openssl/crypto/ec/ec_ameth.c
index 5dbc6f46..604a0e35 100644
--- a/freebsd/crypto/openssl/crypto/ec/ec_ameth.c
+++ b/freebsd/crypto/openssl/crypto/ec/ec_ameth.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -506,7 +506,12 @@ static int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
#endif
case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
- *(int *)arg2 = NID_sha256;
+ if (EVP_PKEY_id(pkey) == EVP_PKEY_SM2) {
+ /* For SM2, the only valid digest-alg is SM3 */
+ *(int *)arg2 = NID_sm3;
+ } else {
+ *(int *)arg2 = NID_sha256;
+ }
return 1;
case ASN1_PKEY_CTRL_SET1_TLS_ENCPT:
diff --git a/freebsd/crypto/openssl/crypto/ec/ec_lib.c b/freebsd/crypto/openssl/crypto/ec/ec_lib.c
index 7f365de3..6da3f8b7 100644
--- a/freebsd/crypto/openssl/crypto/ec/ec_lib.c
+++ b/freebsd/crypto/openssl/crypto/ec/ec_lib.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
* Licensed under the OpenSSL license (the "License"). You may not use
@@ -1076,8 +1076,7 @@ static int ec_field_inverse_mod_ord(const EC_GROUP *group, BIGNUM *r,
ret = 1;
err:
- if (ctx != NULL)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
}
diff --git a/freebsd/crypto/openssl/crypto/ec/ec_mult.c b/freebsd/crypto/openssl/crypto/ec/ec_mult.c
index 5bfa3868..169f8e18 100644
--- a/freebsd/crypto/openssl/crypto/ec/ec_mult.c
+++ b/freebsd/crypto/openssl/crypto/ec/ec_mult.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
* Licensed under the OpenSSL license (the "License"). You may not use
@@ -380,7 +380,7 @@ int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r,
err:
EC_POINT_free(p);
- EC_POINT_free(s);
+ EC_POINT_clear_free(s);
BN_CTX_end(ctx);
return ret;
@@ -443,7 +443,7 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
* scalar multiplication implementation based on a Montgomery ladder,
* with various timing attack defenses.
*/
- if ((scalar != NULL) && (num == 0)) {
+ if ((scalar != group->order) && (scalar != NULL) && (num == 0)) {
/*-
* In this case we want to compute scalar * GeneratorPoint: this
* codepath is reached most prominently by (ephemeral) key
@@ -454,7 +454,7 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
*/
return ec_scalar_mul_ladder(group, r, scalar, NULL, ctx);
}
- if ((scalar == NULL) && (num == 1)) {
+ if ((scalar == NULL) && (num == 1) && (scalars[0] != group->order)) {
/*-
* In this case we want to compute scalar * VariablePoint: this
* codepath is reached most prominently by the second half of ECDH,
@@ -950,8 +950,7 @@ int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
ret = 1;
err:
- if (ctx != NULL)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
EC_ec_pre_comp_free(pre_comp);
if (points) {
diff --git a/freebsd/crypto/openssl/crypto/ec/ec_pmeth.c b/freebsd/crypto/openssl/crypto/ec/ec_pmeth.c
index 41ca7813..ff38664e 100644
--- a/freebsd/crypto/openssl/crypto/ec/ec_pmeth.c
+++ b/freebsd/crypto/openssl/crypto/ec/ec_pmeth.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -325,7 +325,11 @@ static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
EVP_MD_type((const EVP_MD *)p2) != NID_sha224 &&
EVP_MD_type((const EVP_MD *)p2) != NID_sha256 &&
EVP_MD_type((const EVP_MD *)p2) != NID_sha384 &&
- EVP_MD_type((const EVP_MD *)p2) != NID_sha512) {
+ EVP_MD_type((const EVP_MD *)p2) != NID_sha512 &&
+ EVP_MD_type((const EVP_MD *)p2) != NID_sha3_224 &&
+ EVP_MD_type((const EVP_MD *)p2) != NID_sha3_256 &&
+ EVP_MD_type((const EVP_MD *)p2) != NID_sha3_384 &&
+ EVP_MD_type((const EVP_MD *)p2) != NID_sha3_512) {
ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_DIGEST_TYPE);
return 0;
}
diff --git a/freebsd/crypto/openssl/crypto/ec/ecdh_ossl.c b/freebsd/crypto/openssl/crypto/ec/ecdh_ossl.c
index 74d1b73e..6d641991 100644
--- a/freebsd/crypto/openssl/crypto/ec/ecdh_ossl.c
+++ b/freebsd/crypto/openssl/crypto/ec/ecdh_ossl.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
* Licensed under the OpenSSL license (the "License"). You may not use
@@ -114,9 +114,8 @@ int ecdh_simple_compute_key(unsigned char **pout, size_t *poutlen,
ret = 1;
err:
- EC_POINT_free(tmp);
- if (ctx)
- BN_CTX_end(ctx);
+ EC_POINT_clear_free(tmp);
+ BN_CTX_end(ctx);
BN_CTX_free(ctx);
OPENSSL_free(buf);
return ret;
diff --git a/freebsd/crypto/openssl/crypto/ec/ecp_nistp521.c b/freebsd/crypto/openssl/crypto/ec/ecp_nistp521.c
index 96e0d661..2fd19dd0 100644
--- a/freebsd/crypto/openssl/crypto/ec/ecp_nistp521.c
+++ b/freebsd/crypto/openssl/crypto/ec/ecp_nistp521.c
@@ -359,10 +359,15 @@ static void felem_diff64(felem out, const felem in)
static void felem_diff_128_64(largefelem out, const felem in)
{
/*
- * In order to prevent underflow, we add 0 mod p before subtracting.
+ * In order to prevent underflow, we add 64p mod p (which is equivalent
+ * to 0 mod p) before subtracting. p is 2^521 - 1, i.e. in binary a 521
+ * digit number with all bits set to 1. See "The representation of field
+ * elements" comment above for a description of how limbs are used to
+ * represent a number. 64p is represented with 8 limbs containing a number
+ * with 58 bits set and one limb with a number with 57 bits set.
*/
- static const limb two63m6 = (((limb) 1) << 62) - (((limb) 1) << 5);
- static const limb two63m5 = (((limb) 1) << 62) - (((limb) 1) << 4);
+ static const limb two63m6 = (((limb) 1) << 63) - (((limb) 1) << 6);
+ static const limb two63m5 = (((limb) 1) << 63) - (((limb) 1) << 5);
out[0] += two63m6 - in[0];
out[1] += two63m5 - in[1];
diff --git a/freebsd/crypto/openssl/crypto/ec/ecp_nistz256.c b/freebsd/crypto/openssl/crypto/ec/ecp_nistz256.c
index 9a370643..e6ed24ab 100644
--- a/freebsd/crypto/openssl/crypto/ec/ecp_nistz256.c
+++ b/freebsd/crypto/openssl/crypto/ec/ecp_nistz256.c
@@ -890,8 +890,7 @@ __owur static int ecp_nistz256_mult_precompute(EC_GROUP *group, BN_CTX *ctx)
ret = 1;
err:
- if (ctx != NULL)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
EC_nistz256_pre_comp_free(pre_comp);
diff --git a/freebsd/crypto/openssl/crypto/ec/ecp_smpl.c b/freebsd/crypto/openssl/crypto/ec/ecp_smpl.c
index c1f456fe..1b8d298f 100644
--- a/freebsd/crypto/openssl/crypto/ec/ecp_smpl.c
+++ b/freebsd/crypto/openssl/crypto/ec/ecp_smpl.c
@@ -309,8 +309,7 @@ int ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
ret = 1;
err:
- if (ctx != NULL)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
}
@@ -789,8 +788,7 @@ int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
ret = 1;
end:
- if (ctx) /* otherwise we already called BN_CTX_end */
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
}
diff --git a/freebsd/crypto/openssl/crypto/err/err.c b/freebsd/crypto/openssl/crypto/err/err.c
index 36f9579c..806dae3f 100644
--- a/freebsd/crypto/openssl/crypto/err/err.c
+++ b/freebsd/crypto/openssl/crypto/err/err.c
@@ -525,8 +525,24 @@ static unsigned long get_error_values(int inc, int top, const char **file,
return ERR_R_INTERNAL_ERROR;
}
+ while (es->bottom != es->top) {
+ if (es->err_flags[es->top] & ERR_FLAG_CLEAR) {
+ err_clear(es, es->top);
+ es->top = es->top > 0 ? es->top - 1 : ERR_NUM_ERRORS - 1;
+ continue;
+ }
+ i = (es->bottom + 1) % ERR_NUM_ERRORS;
+ if (es->err_flags[i] & ERR_FLAG_CLEAR) {
+ es->bottom = i;
+ err_clear(es, es->bottom);
+ continue;
+ }
+ break;
+ }
+
if (es->bottom == es->top)
return 0;
+
if (top)
i = es->top; /* last error */
else
@@ -915,25 +931,6 @@ int ERR_clear_last_mark(void)
return 1;
}
-#ifdef UINTPTR_T
-# undef UINTPTR_T
-#endif
-/*
- * uintptr_t is the answer, but unfortunately C89, current "least common
- * denominator" doesn't define it. Most legacy platforms typedef it anyway,
- * so that attempt to fill the gaps means that one would have to identify
- * that track these gaps, which would be undesirable. Macro it is...
- */
-#if defined(__VMS) && __INITIAL_POINTER_SIZE==64
-/*
- * But we can't use size_t on VMS, because it adheres to sizeof(size_t)==4
- * even in 64-bit builds, which means that it won't work as mask.
- */
-# define UINTPTR_T unsigned long long
-#else
-# define UINTPTR_T size_t
-#endif
-
void err_clear_last_constant_time(int clear)
{
ERR_STATE *es;
@@ -945,11 +942,11 @@ void err_clear_last_constant_time(int clear)
top = es->top;
- es->err_flags[top] &= ~(0 - clear);
- es->err_buffer[top] &= ~(0UL - clear);
- es->err_file[top] = (const char *)((UINTPTR_T)es->err_file[top] &
- ~((UINTPTR_T)0 - clear));
- es->err_line[top] |= 0 - clear;
-
- es->top = (top + ERR_NUM_ERRORS - clear) % ERR_NUM_ERRORS;
+ /*
+ * Flag error as cleared but remove it elsewhere to avoid two errors
+ * accessing the same error stack location, revealing timing information.
+ */
+ clear = constant_time_select_int(constant_time_eq_int(clear, 0),
+ 0, ERR_FLAG_CLEAR);
+ es->err_flags[top] |= clear;
}
diff --git a/freebsd/crypto/openssl/crypto/evp/digest.c b/freebsd/crypto/openssl/crypto/evp/digest.c
index 9111c19a..82e7bac8 100644
--- a/freebsd/crypto/openssl/crypto/evp/digest.c
+++ b/freebsd/crypto/openssl/crypto/evp/digest.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -152,6 +152,9 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data, size_t count)
{
+ if (count == 0)
+ return 1;
+
return ctx->update(ctx, data, count);
}
diff --git a/freebsd/crypto/openssl/crypto/evp/e_aes.c b/freebsd/crypto/openssl/crypto/evp/e_aes.c
index 1c86559f..1d025fe1 100644
--- a/freebsd/crypto/openssl/crypto/evp/e_aes.c
+++ b/freebsd/crypto/openssl/crypto/evp/e_aes.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -2218,9 +2218,6 @@ static int s390x_aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
if (!cctx->aes.ccm.iv_set)
return -1;
- if (!enc && !cctx->aes.ccm.tag_set)
- return -1;
-
if (out == NULL) {
/* Update(): Pass message length. */
if (in == NULL) {
@@ -2239,6 +2236,10 @@ static int s390x_aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
return len;
}
+ /* The tag must be set before actually decrypting data */
+ if (!enc && !cctx->aes.ccm.tag_set)
+ return -1;
+
/* Update(): Process message. */
if (!cctx->aes.ccm.len_set) {
@@ -3645,8 +3646,6 @@ static int aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
if (!cctx->iv_set)
return -1;
- if (!EVP_CIPHER_CTX_encrypting(ctx) && !cctx->tag_set)
- return -1;
if (!out) {
if (!in) {
if (CRYPTO_ccm128_setiv(ccm, EVP_CIPHER_CTX_iv_noconst(ctx),
@@ -3661,6 +3660,11 @@ static int aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
CRYPTO_ccm128_aad(ccm, in, len);
return len;
}
+
+ /* The tag must be set before actually decrypting data */
+ if (!EVP_CIPHER_CTX_encrypting(ctx) && !cctx->tag_set)
+ return -1;
+
/* If not set length yet do it */
if (!cctx->len_set) {
if (CRYPTO_ccm128_setiv(ccm, EVP_CIPHER_CTX_iv_noconst(ctx),
diff --git a/freebsd/crypto/openssl/crypto/evp/e_aria.c b/freebsd/crypto/openssl/crypto/evp/e_aria.c
index 33ff1186..6a9d5dee 100644
--- a/freebsd/crypto/openssl/crypto/evp/e_aria.c
+++ b/freebsd/crypto/openssl/crypto/evp/e_aria.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
@@ -488,6 +488,16 @@ static int aria_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
return 0;
}
+static int aria_gcm_cleanup(EVP_CIPHER_CTX *ctx)
+{
+ EVP_ARIA_GCM_CTX *gctx = EVP_C_DATA(EVP_ARIA_GCM_CTX, ctx);
+
+ if (gctx->iv != EVP_CIPHER_CTX_iv_noconst(ctx))
+ OPENSSL_free(gctx->iv);
+
+ return 1;
+}
+
static int aria_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
@@ -729,6 +739,8 @@ static int aria_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
}
}
+#define aria_ccm_cleanup NULL
+
#define ARIA_AUTH_FLAGS (EVP_CIPH_FLAG_DEFAULT_ASN1 \
| EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \
| EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \
@@ -741,7 +753,7 @@ static const EVP_CIPHER aria_##keylen##_##mode = { \
ARIA_AUTH_FLAGS|EVP_CIPH_##MODE##_MODE, \
aria_##mode##_init_key, \
aria_##mode##_cipher, \
- NULL, \
+ aria_##mode##_cleanup, \
sizeof(EVP_ARIA_##MODE##_CTX), \
NULL,NULL,aria_##mode##_ctrl,NULL }; \
const EVP_CIPHER *EVP_aria_##keylen##_##mode(void) \
diff --git a/freebsd/crypto/openssl/crypto/evp/e_chacha20_poly1305.c b/freebsd/crypto/openssl/crypto/evp/e_chacha20_poly1305.c
index 3f73fd19..4eeb7bc3 100644
--- a/freebsd/crypto/openssl/crypto/evp/e_chacha20_poly1305.c
+++ b/freebsd/crypto/openssl/crypto/evp/e_chacha20_poly1305.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -32,6 +32,8 @@ typedef struct {
#define data(ctx) ((EVP_CHACHA_KEY *)(ctx)->cipher_data)
+#define CHACHA20_POLY1305_MAX_IVLEN 12
+
static int chacha_init_key(EVP_CIPHER_CTX *ctx,
const unsigned char user_key[CHACHA_KEY_SIZE],
const unsigned char iv[CHACHA_CTR_SIZE], int enc)
@@ -535,7 +537,7 @@ static int chacha20_poly1305_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg,
return 1;
case EVP_CTRL_AEAD_SET_IVLEN:
- if (arg <= 0 || arg > CHACHA_CTR_SIZE)
+ if (arg <= 0 || arg > CHACHA20_POLY1305_MAX_IVLEN)
return 0;
actx->nonce_len = arg;
return 1;
diff --git a/freebsd/crypto/openssl/crypto/evp/p_lib.c b/freebsd/crypto/openssl/crypto/evp/p_lib.c
index 47135f0d..57c9ddf0 100644
--- a/freebsd/crypto/openssl/crypto/evp/p_lib.c
+++ b/freebsd/crypto/openssl/crypto/evp/p_lib.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -396,6 +396,11 @@ int EVP_PKEY_set1_engine(EVP_PKEY *pkey, ENGINE *e)
pkey->pmeth_engine = e;
return 1;
}
+
+ENGINE *EVP_PKEY_get0_engine(const EVP_PKEY *pkey)
+{
+ return pkey->engine;
+}
#endif
int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key)
{
diff --git a/freebsd/crypto/openssl/crypto/evp/p_open.c b/freebsd/crypto/openssl/crypto/evp/p_open.c
index 8d558e9a..4bf70034 100644
--- a/freebsd/crypto/openssl/crypto/evp/p_open.c
+++ b/freebsd/crypto/openssl/crypto/evp/p_open.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -42,7 +42,7 @@ int EVP_OpenInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
}
size = EVP_PKEY_size(priv);
- key = OPENSSL_malloc(size + 2);
+ key = OPENSSL_malloc(size);
if (key == NULL) {
/* ERROR */
EVPerr(EVP_F_EVP_OPENINIT, ERR_R_MALLOC_FAILURE);
diff --git a/freebsd/crypto/openssl/crypto/hmac/hmac.c b/freebsd/crypto/openssl/crypto/hmac/hmac.c
index 8d1fd286..29978df2 100644
--- a/freebsd/crypto/openssl/crypto/hmac/hmac.c
+++ b/freebsd/crypto/openssl/crypto/hmac/hmac.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -37,6 +37,13 @@ int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,
return 0;
}
+ /*
+ * The HMAC construction is not allowed to be used with the
+ * extendable-output functions (XOF) shake128 and shake256.
+ */
+ if ((EVP_MD_meth_get_flags(md) & EVP_MD_FLAG_XOF) != 0)
+ return 0;
+
if (key != NULL) {
reset = 1;
j = EVP_MD_block_size(md);
diff --git a/freebsd/crypto/openssl/crypto/include/internal/dso_conf.h b/freebsd/crypto/openssl/crypto/include/internal/dso_conf.h
index 5bef4afd..61985cac 100644
--- a/freebsd/crypto/openssl/crypto/include/internal/dso_conf.h
+++ b/freebsd/crypto/openssl/crypto/include/internal/dso_conf.h
@@ -2,7 +2,7 @@
/* WARNING: do not edit! */
/* Generated by Makefile from crypto/include/internal/dso_conf.h.in */
/*
- * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -12,9 +12,7 @@
#ifndef HEADER_DSO_CONF_H
# define HEADER_DSO_CONF_H
-
# define DSO_DLFCN
# define HAVE_DLFCN_H
# define DSO_EXTENSION ".so"
-
#endif
diff --git a/freebsd/crypto/openssl/crypto/init.c b/freebsd/crypto/openssl/crypto/init.c
index e409911d..e1d27815 100644
--- a/freebsd/crypto/openssl/crypto/init.c
+++ b/freebsd/crypto/openssl/crypto/init.c
@@ -167,10 +167,9 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_load_crypto_nodelete)
#ifdef OPENSSL_INIT_DEBUG
fprintf(stderr, "OPENSSL_INIT: ossl_init_load_crypto_nodelete()\n");
#endif
-#if !defined(OPENSSL_NO_DSO) \
- && !defined(OPENSSL_USE_NODELETE) \
+#if !defined(OPENSSL_USE_NODELETE) \
&& !defined(OPENSSL_NO_PINSHARED)
-# ifdef DSO_WIN32
+# if defined(DSO_WIN32) && !defined(_WIN32_WCE)
{
HMODULE handle = NULL;
BOOL ret;
@@ -186,7 +185,7 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_load_crypto_nodelete)
# endif
return (ret == TRUE) ? 1 : 0;
}
-# else
+# elif !defined(DSO_NONE) && !defined(__rtems__)
/*
* Deliberately leak a reference to ourselves. This will force the library
* to remain loaded until the atexit() handler is run at process exit.
@@ -714,7 +713,7 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
ret = RUN_ONCE(&config, ossl_init_config);
conf_settings = NULL;
CRYPTO_THREAD_unlock(init_lock);
- if (!ret)
+ if (ret <= 0)
return 0;
}
@@ -779,8 +778,7 @@ int OPENSSL_atexit(void (*handler)(void))
{
OPENSSL_INIT_STOP *newhand;
-#if !defined(OPENSSL_NO_DSO) \
- && !defined(OPENSSL_USE_NODELETE)\
+#if !defined(OPENSSL_USE_NODELETE)\
&& !defined(OPENSSL_NO_PINSHARED)
{
union {
@@ -789,7 +787,7 @@ int OPENSSL_atexit(void (*handler)(void))
} handlersym;
handlersym.func = handler;
-# ifdef DSO_WIN32
+# if defined(DSO_WIN32) && !defined(_WIN32_WCE)
{
HMODULE handle = NULL;
BOOL ret;
@@ -805,7 +803,7 @@ int OPENSSL_atexit(void (*handler)(void))
if (!ret)
return 0;
}
-# else
+# elif !defined(DSO_NONE)
/*
* Deliberately leak a reference to the handler. This will force the
* library/code containing the handler to remain loaded until we run the
diff --git a/freebsd/crypto/openssl/crypto/mips_arch.h b/freebsd/crypto/openssl/crypto/mips_arch.h
index 75043e79..e18ac072 100644
--- a/freebsd/crypto/openssl/crypto/mips_arch.h
+++ b/freebsd/crypto/openssl/crypto/mips_arch.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2011-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -11,7 +11,7 @@
# define __MIPS_ARCH_H__
# if (defined(__mips_smartmips) || defined(_MIPS_ARCH_MIPS32R3) || \
- defined(_MIPS_ARCH_MIPS32R5) || defined(_MIPS_ARCH_MIPS32R6))
+ defined(_MIPS_ARCH_MIPS32R5) || defined(_MIPS_ARCH_MIPS32R6)) \
&& !defined(_MIPS_ARCH_MIPS32R2)
# define _MIPS_ARCH_MIPS32R2
# endif
diff --git a/freebsd/crypto/openssl/crypto/modes/ccm128.c b/freebsd/crypto/openssl/crypto/modes/ccm128.c
index 96a35313..d96dd45a 100644
--- a/freebsd/crypto/openssl/crypto/modes/ccm128.c
+++ b/freebsd/crypto/openssl/crypto/modes/ccm128.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2011-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -427,7 +427,7 @@ size_t CRYPTO_ccm128_tag(CCM128_CONTEXT *ctx, unsigned char *tag, size_t len)
M *= 2;
M += 2;
- if (len < M)
+ if (len != M)
return 0;
memcpy(tag, ctx->cmac.c, M);
return M;
diff --git a/freebsd/crypto/openssl/crypto/o_str.c b/freebsd/crypto/openssl/crypto/o_str.c
index f02ef56c..79d72a2c 100644
--- a/freebsd/crypto/openssl/crypto/o_str.c
+++ b/freebsd/crypto/openssl/crypto/o_str.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 2003-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2003-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -225,7 +225,26 @@ int openssl_strerror_r(int errnum, char *buf, size_t buflen)
#if defined(_MSC_VER) && _MSC_VER>=1400
return !strerror_s(buf, buflen, errnum);
#elif defined(_GNU_SOURCE)
- return strerror_r(errnum, buf, buflen) != NULL;
+ char *err;
+
+ /*
+ * GNU strerror_r may not actually set buf.
+ * It can return a pointer to some (immutable) static string in which case
+ * buf is left unused.
+ */
+ err = strerror_r(errnum, buf, buflen);
+ if (err == NULL)
+ return 0;
+ /*
+ * If err is statically allocated, err != buf and we need to copy the data.
+ * If err points somewhere inside buf, OPENSSL_strlcpy can handle this,
+ * since src and dest are not annotated with __restrict and the function
+ * reads src byte for byte and writes to dest.
+ * If err == buf we do not have to copy anything.
+ */
+ if (err != buf)
+ OPENSSL_strlcpy(buf, err, buflen);
+ return 1;
#elif (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) || \
(defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 600)
/*
@@ -236,6 +255,7 @@ int openssl_strerror_r(int errnum, char *buf, size_t buflen)
return !strerror_r(errnum, buf, buflen);
#else
char *err;
+
/* Fall back to non-thread safe strerror()...its all we can do */
if (buflen < 2)
return 0;
@@ -243,8 +263,7 @@ int openssl_strerror_r(int errnum, char *buf, size_t buflen)
/* Can this ever happen? */
if (err == NULL)
return 0;
- strncpy(buf, err, buflen - 1);
- buf[buflen - 1] = '\0';
+ OPENSSL_strlcpy(buf, err, buflen);
return 1;
#endif
}
diff --git a/freebsd/crypto/openssl/crypto/objects/obj_dat.h b/freebsd/crypto/openssl/crypto/objects/obj_dat.h
index 9ab1a14b..ea91db66 100644
--- a/freebsd/crypto/openssl/crypto/objects/obj_dat.h
+++ b/freebsd/crypto/openssl/crypto/objects/obj_dat.h
@@ -1070,7 +1070,7 @@ static const unsigned char so[7762] = {
0x2A,0x85,0x03,0x07,0x01,0x01,0x07,0x01, /* [ 7684] OBJ_id_tc26_wrap_gostr3412_2015_magma */
0x2A,0x85,0x03,0x07,0x01,0x01,0x07,0x01,0x01, /* [ 7692] OBJ_id_tc26_wrap_gostr3412_2015_magma_kexp15 */
0x2A,0x85,0x03,0x07,0x01,0x01,0x07,0x02, /* [ 7701] OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik */
- 0x2A,0x85,0x03,0x07,0x01,0x01,0x07,0x01,0x01, /* [ 7709] OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 */
+ 0x2A,0x85,0x03,0x07,0x01,0x01,0x07,0x02,0x01, /* [ 7709] OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 */
0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x01,0x02, /* [ 7718] OBJ_id_tc26_gost_3410_2012_256_paramSetB */
0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x01,0x03, /* [ 7727] OBJ_id_tc26_gost_3410_2012_256_paramSetC */
0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x01,0x04, /* [ 7736] OBJ_id_tc26_gost_3410_2012_256_paramSetD */
@@ -5364,7 +5364,7 @@ static const unsigned int obj_objs[NUM_OBJ] = {
1177, /* OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm 1 2 643 7 1 1 5 2 1 */
1178, /* OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac 1 2 643 7 1 1 5 2 2 */
1181, /* OBJ_id_tc26_wrap_gostr3412_2015_magma_kexp15 1 2 643 7 1 1 7 1 1 */
- 1183, /* OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 1 2 643 7 1 1 7 1 1 */
+ 1183, /* OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 1 2 643 7 1 1 7 2 1 */
1148, /* OBJ_id_tc26_gost_3410_2012_256_paramSetA 1 2 643 7 1 2 1 1 1 */
1184, /* OBJ_id_tc26_gost_3410_2012_256_paramSetB 1 2 643 7 1 2 1 1 2 */
1185, /* OBJ_id_tc26_gost_3410_2012_256_paramSetC 1 2 643 7 1 2 1 1 3 */
diff --git a/freebsd/crypto/openssl/crypto/ocsp/ocsp_ext.c b/freebsd/crypto/openssl/crypto/ocsp/ocsp_ext.c
index d4efda7c..ea2f6289 100644
--- a/freebsd/crypto/openssl/crypto/ocsp/ocsp_ext.c
+++ b/freebsd/crypto/openssl/crypto/ocsp/ocsp_ext.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -441,6 +441,7 @@ X509_EXTENSION *OCSP_url_svcloc_new(X509_NAME *issuer, const char **urls)
if ((sloc = OCSP_SERVICELOC_new()) == NULL)
goto err;
+ X509_NAME_free(sloc->issuer);
if ((sloc->issuer = X509_NAME_dup(issuer)) == NULL)
goto err;
if (urls && *urls
@@ -451,12 +452,11 @@ X509_EXTENSION *OCSP_url_svcloc_new(X509_NAME *issuer, const char **urls)
goto err;
if ((ad->method = OBJ_nid2obj(NID_ad_OCSP)) == NULL)
goto err;
- if ((ad->location = GENERAL_NAME_new()) == NULL)
- goto err;
if ((ia5 = ASN1_IA5STRING_new()) == NULL)
goto err;
if (!ASN1_STRING_set((ASN1_STRING *)ia5, *urls, -1))
goto err;
+ /* ad->location is allocated inside ACCESS_DESCRIPTION_new */
ad->location->type = GEN_URI;
ad->location->d.ia5 = ia5;
ia5 = NULL;
diff --git a/freebsd/crypto/openssl/crypto/ocsp/ocsp_lib.c b/freebsd/crypto/openssl/crypto/ocsp/ocsp_lib.c
index a9c05dd3..e4331eb9 100644
--- a/freebsd/crypto/openssl/crypto/ocsp/ocsp_lib.c
+++ b/freebsd/crypto/openssl/crypto/ocsp/ocsp_lib.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -90,7 +90,7 @@ OCSP_CERTID *OCSP_cert_id_new(const EVP_MD *dgst,
return NULL;
}
-int OCSP_id_issuer_cmp(OCSP_CERTID *a, OCSP_CERTID *b)
+int OCSP_id_issuer_cmp(const OCSP_CERTID *a, const OCSP_CERTID *b)
{
int ret;
ret = OBJ_cmp(a->hashAlgorithm.algorithm, b->hashAlgorithm.algorithm);
@@ -102,7 +102,7 @@ int OCSP_id_issuer_cmp(OCSP_CERTID *a, OCSP_CERTID *b)
return ASN1_OCTET_STRING_cmp(&a->issuerKeyHash, &b->issuerKeyHash);
}
-int OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b)
+int OCSP_id_cmp(const OCSP_CERTID *a, const OCSP_CERTID *b)
{
int ret;
ret = OCSP_id_issuer_cmp(a, b);
diff --git a/freebsd/crypto/openssl/crypto/pem/pem_sign.c b/freebsd/crypto/openssl/crypto/pem/pem_sign.c
index 5f35af05..6bf4c39c 100644
--- a/freebsd/crypto/openssl/crypto/pem/pem_sign.c
+++ b/freebsd/crypto/openssl/crypto/pem/pem_sign.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -33,7 +33,7 @@ int PEM_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
int i, ret = 0;
unsigned int m_len;
- m = OPENSSL_malloc(EVP_PKEY_size(pkey) + 2);
+ m = OPENSSL_malloc(EVP_PKEY_size(pkey));
if (m == NULL) {
PEMerr(PEM_F_PEM_SIGNFINAL, ERR_R_MALLOC_FAILURE);
goto err;
diff --git a/freebsd/crypto/openssl/crypto/rand/drbg_lib.c b/freebsd/crypto/openssl/crypto/rand/drbg_lib.c
index 86dd1166..48f941ba 100644
--- a/freebsd/crypto/openssl/crypto/rand/drbg_lib.c
+++ b/freebsd/crypto/openssl/crypto/rand/drbg_lib.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2011-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -190,8 +190,8 @@ static RAND_DRBG *rand_drbg_new(int secure,
unsigned int flags,
RAND_DRBG *parent)
{
- RAND_DRBG *drbg = secure ?
- OPENSSL_secure_zalloc(sizeof(*drbg)) : OPENSSL_zalloc(sizeof(*drbg));
+ RAND_DRBG *drbg = secure ? OPENSSL_secure_zalloc(sizeof(*drbg))
+ : OPENSSL_zalloc(sizeof(*drbg));
if (drbg == NULL) {
RANDerr(RAND_F_RAND_DRBG_NEW, ERR_R_MALLOC_FAILURE);
diff --git a/freebsd/crypto/openssl/crypto/rand/rand_lib.c b/freebsd/crypto/openssl/crypto/rand/rand_lib.c
index a6553d78..ea07ac6c 100644
--- a/freebsd/crypto/openssl/crypto/rand/rand_lib.c
+++ b/freebsd/crypto/openssl/crypto/rand/rand_lib.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -139,7 +139,7 @@ size_t rand_drbg_get_entropy(RAND_DRBG *drbg,
size_t entropy_available = 0;
RAND_POOL *pool;
- if (drbg->parent && drbg->strength > drbg->parent->strength) {
+ if (drbg->parent != NULL && drbg->strength > drbg->parent->strength) {
/*
* We currently don't support the algorithm from NIST SP 800-90C
* 10.1.2 to use a weaker DRBG as source
@@ -157,7 +157,7 @@ size_t rand_drbg_get_entropy(RAND_DRBG *drbg,
return 0;
}
- if (drbg->parent) {
+ if (drbg->parent != NULL) {
size_t bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
unsigned char *buffer = rand_pool_add_begin(pool, bytes_needed);
@@ -237,7 +237,7 @@ size_t rand_drbg_get_nonce(RAND_DRBG *drbg,
struct {
void * instance;
int count;
- } data = { 0 };
+ } data = { NULL, 0 };
pool = rand_pool_new(0, min_len, max_len);
if (pool == NULL)
@@ -404,7 +404,7 @@ int RAND_poll(void)
} else {
/* fill random pool and seed the current legacy RNG */
pool = rand_pool_new(RAND_DRBG_STRENGTH,
- RAND_DRBG_STRENGTH / 8,
+ (RAND_DRBG_STRENGTH + 7) / 8,
RAND_POOL_MAX_LENGTH);
if (pool == NULL)
return 0;
@@ -691,7 +691,7 @@ unsigned char *rand_pool_add_begin(RAND_POOL *pool, size_t len)
if (pool->buffer == NULL) {
RANDerr(RAND_F_RAND_POOL_ADD_BEGIN, ERR_R_INTERNAL_ERROR);
- return 0;
+ return NULL;
}
return pool->buffer + pool->len;
diff --git a/freebsd/crypto/openssl/crypto/rand/rand_unix.c b/freebsd/crypto/openssl/crypto/rand/rand_unix.c
index d6eae343..a5d658e0 100644
--- a/freebsd/crypto/openssl/crypto/rand/rand_unix.c
+++ b/freebsd/crypto/openssl/crypto/rand/rand_unix.c
@@ -21,7 +21,7 @@
#include <stdio.h>
#include "internal/dso.h"
#if defined(__linux)
-# include <sys/syscall.h>
+# include <asm/unistd.h>
#endif
#if defined(__FreeBSD__)
# include <sys/types.h>
@@ -326,8 +326,8 @@ static ssize_t syscall_random(void *buf, size_t buflen)
# endif
/* Linux supports this since version 3.17 */
-# if defined(__linux) && defined(SYS_getrandom)
- return syscall(SYS_getrandom, buf, buflen, 0);
+# if defined(__linux) && defined(__NR_getrandom)
+ return syscall(__NR_getrandom, buf, buflen, 0);
# elif (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(KERN_ARND)
return sysctl_random(buf, buflen);
# else
@@ -512,6 +512,29 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool)
bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
{
size_t i;
+#ifdef DEVRANDOM_WAIT
+ static int wait_done = 0;
+
+ /*
+ * On some implementations reading from /dev/urandom is possible
+ * before it is initialized. Therefore we wait for /dev/random
+ * to be readable to make sure /dev/urandom is initialized.
+ */
+ if (!wait_done && bytes_needed > 0) {
+ int f = open(DEVRANDOM_WAIT, O_RDONLY);
+
+ if (f >= 0) {
+ fd_set fds;
+
+ FD_ZERO(&fds);
+ FD_SET(f, &fds);
+ while (select(f+1, &fds, NULL, NULL, NULL) < 0
+ && errno == EINTR);
+ close(f);
+ }
+ wait_done = 1;
+ }
+#endif
for (i = 0; bytes_needed > 0 && i < OSSL_NELEM(random_device_paths); i++) {
ssize_t bytes = 0;
diff --git a/freebsd/crypto/openssl/crypto/rand/randfile.c b/freebsd/crypto/openssl/crypto/rand/randfile.c
index de3c15dc..44db456f 100644
--- a/freebsd/crypto/openssl/crypto/rand/randfile.c
+++ b/freebsd/crypto/openssl/crypto/rand/randfile.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -256,7 +256,7 @@ const char *RAND_file_name(char *buf, size_t size)
size_t len;
int use_randfile = 1;
-#if defined(_WIN32) && defined(CP_UTF8)
+#if defined(_WIN32) && defined(CP_UTF8) && !defined(_WIN32_WCE)
DWORD envlen;
WCHAR *var;
diff --git a/freebsd/crypto/openssl/crypto/rsa/rsa_ameth.c b/freebsd/crypto/openssl/crypto/rsa/rsa_ameth.c
index ce3d0eee..a23e2483 100644
--- a/freebsd/crypto/openssl/crypto/rsa/rsa_ameth.c
+++ b/freebsd/crypto/openssl/crypto/rsa/rsa_ameth.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -585,10 +585,12 @@ static RSA_PSS_PARAMS *rsa_ctx_to_pss(EVP_PKEY_CTX *pkctx)
return NULL;
if (saltlen == -1) {
saltlen = EVP_MD_size(sigmd);
- } else if (saltlen == -2) {
+ } else if (saltlen == -2 || saltlen == -3) {
saltlen = EVP_PKEY_size(pk) - EVP_MD_size(sigmd) - 2;
if ((EVP_PKEY_bits(pk) & 0x7) == 1)
saltlen--;
+ if (saltlen < 0)
+ return NULL;
}
return rsa_pss_params_create(sigmd, mgf1md, saltlen);
diff --git a/freebsd/crypto/openssl/crypto/rsa/rsa_gen.c b/freebsd/crypto/openssl/crypto/rsa/rsa_gen.c
index 8143555e..22d99bb4 100644
--- a/freebsd/crypto/openssl/crypto/rsa/rsa_gen.c
+++ b/freebsd/crypto/openssl/crypto/rsa/rsa_gen.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -389,8 +389,7 @@ static int rsa_builtin_keygen(RSA *rsa, int bits, int primes, BIGNUM *e_value,
RSAerr(RSA_F_RSA_BUILTIN_KEYGEN, ERR_LIB_BN);
ok = 0;
}
- if (ctx != NULL)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(ctx);
return ok;
}
diff --git a/freebsd/crypto/openssl/crypto/rsa/rsa_oaep.c b/freebsd/crypto/openssl/crypto/rsa/rsa_oaep.c
index ca0314ff..a5e97506 100644
--- a/freebsd/crypto/openssl/crypto/rsa/rsa_oaep.c
+++ b/freebsd/crypto/openssl/crypto/rsa/rsa_oaep.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -145,7 +145,7 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
* |num| is the length of the modulus; |flen| is the length of the
* encoded message. Therefore, for any |from| that was obtained by
* decrypting a ciphertext, we must have |flen| <= |num|. Similarly,
- * num < 2 * mdlen + 2 must hold for the modulus irrespective of
+ * |num| >= 2 * |mdlen| + 2 must hold for the modulus irrespective of
* the ciphertext, see PKCS #1 v2.2, section 7.1.2.
* This does not leak any side-channel information.
*/
@@ -181,17 +181,16 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
from -= 1 & mask;
*--em = *from & mask;
}
- from = em;
/*
* The first byte must be zero, however we must not leak if this is
* true. See James H. Manger, "A Chosen Ciphertext Attack on RSA
* Optimal Asymmetric Encryption Padding (OAEP) [...]", CRYPTO 2001).
*/
- good = constant_time_is_zero(from[0]);
+ good = constant_time_is_zero(em[0]);
- maskedseed = from + 1;
- maskeddb = from + 1 + mdlen;
+ maskedseed = em + 1;
+ maskeddb = em + 1 + mdlen;
if (PKCS1_MGF1(seed, mdlen, maskeddb, dblen, mgf1md))
goto cleanup;
@@ -232,29 +231,30 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
mlen = dblen - msg_index;
/*
- * For good measure, do this check in constant tine as well.
+ * For good measure, do this check in constant time as well.
*/
good &= constant_time_ge(tlen, mlen);
/*
- * Even though we can't fake result's length, we can pretend copying
- * |tlen| bytes where |mlen| bytes would be real. Last |tlen| of |dblen|
- * bytes are viewed as circular buffer with start at |tlen|-|mlen'|,
- * where |mlen'| is "saturated" |mlen| value. Deducing information
- * about failure or |mlen| would take attacker's ability to observe
- * memory access pattern with byte granularity *as it occurs*. It
- * should be noted that failure is indistinguishable from normal
- * operation if |tlen| is fixed by protocol.
+ * Move the result in-place by |dblen|-|mdlen|-1-|mlen| bytes to the left.
+ * Then if |good| move |mlen| bytes from |db|+|mdlen|+1 to |to|.
+ * Otherwise leave |to| unchanged.
+ * Copy the memory back in a way that does not reveal the size of
+ * the data being copied via a timing side channel. This requires copying
+ * parts of the buffer multiple times based on the bits set in the real
+ * length. Clear bits do a non-copy with identical access pattern.
+ * The loop below has overall complexity of O(N*log(N)).
*/
- tlen = constant_time_select_int(constant_time_lt(dblen, tlen), dblen, tlen);
- msg_index = constant_time_select_int(good, msg_index, dblen - tlen);
- mlen = dblen - msg_index;
- for (from = db + msg_index, mask = good, i = 0; i < tlen; i++) {
- unsigned int equals = constant_time_eq(i, mlen);
-
- from -= dblen & equals; /* if (i == dblen) rewind */
- mask &= mask ^ equals; /* if (i == dblen) mask = 0 */
- to[i] = constant_time_select_8(mask, from[i], to[i]);
+ tlen = constant_time_select_int(constant_time_lt(dblen - mdlen - 1, tlen),
+ dblen - mdlen - 1, tlen);
+ for (msg_index = 1; msg_index < dblen - mdlen - 1; msg_index <<= 1) {
+ mask = ~constant_time_eq(msg_index & (dblen - mdlen - 1 - mlen), 0);
+ for (i = mdlen + 1; i < dblen - msg_index; i++)
+ db[i] = constant_time_select_8(mask, db[i + msg_index], db[i]);
+ }
+ for (i = 0; i < tlen; i++) {
+ mask = good & constant_time_lt(i, mlen);
+ to[i] = constant_time_select_8(mask, db[i + mdlen + 1], to[i]);
}
/*
diff --git a/freebsd/crypto/openssl/crypto/rsa/rsa_ossl.c b/freebsd/crypto/openssl/crypto/rsa/rsa_ossl.c
index 2257ba18..2c9ded71 100644
--- a/freebsd/crypto/openssl/crypto/rsa/rsa_ossl.c
+++ b/freebsd/crypto/openssl/crypto/rsa/rsa_ossl.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -150,8 +150,7 @@ static int rsa_ossl_public_encrypt(int flen, const unsigned char *from,
*/
r = BN_bn2binpad(ret, to, num);
err:
- if (ctx != NULL)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(ctx);
OPENSSL_clear_free(buf, num);
return r;
@@ -356,8 +355,7 @@ static int rsa_ossl_private_encrypt(int flen, const unsigned char *from,
*/
r = BN_bn2binpad(res, to, num);
err:
- if (ctx != NULL)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(ctx);
OPENSSL_clear_free(buf, num);
return r;
@@ -483,11 +481,10 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from,
goto err;
}
RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, RSA_R_PADDING_CHECK_FAILED);
- err_clear_last_constant_time(r >= 0);
+ err_clear_last_constant_time(1 & ~constant_time_msb(r));
err:
- if (ctx != NULL)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(ctx);
OPENSSL_clear_free(buf, num);
return r;
@@ -583,8 +580,7 @@ static int rsa_ossl_public_decrypt(int flen, const unsigned char *from,
RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_PADDING_CHECK_FAILED);
err:
- if (ctx != NULL)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(ctx);
OPENSSL_clear_free(buf, num);
return r;
diff --git a/freebsd/crypto/openssl/crypto/rsa/rsa_pk1.c b/freebsd/crypto/openssl/crypto/rsa/rsa_pk1.c
index 09b47e59..429be508 100644
--- a/freebsd/crypto/openssl/crypto/rsa/rsa_pk1.c
+++ b/freebsd/crypto/openssl/crypto/rsa/rsa_pk1.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -194,15 +194,14 @@ int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen,
from -= 1 & mask;
*--em = *from & mask;
}
- from = em;
- good = constant_time_is_zero(from[0]);
- good &= constant_time_eq(from[1], 2);
+ good = constant_time_is_zero(em[0]);
+ good &= constant_time_eq(em[1], 2);
/* scan over padding data */
found_zero_byte = 0;
for (i = 2; i < num; i++) {
- unsigned int equals0 = constant_time_is_zero(from[i]);
+ unsigned int equals0 = constant_time_is_zero(em[i]);
zero_index = constant_time_select_int(~found_zero_byte & equals0,
i, zero_index);
@@ -210,7 +209,7 @@ int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen,
}
/*
- * PS must be at least 8 bytes long, and it starts two bytes into |from|.
+ * PS must be at least 8 bytes long, and it starts two bytes into |em|.
* If we never found a 0-byte, then |zero_index| is 0 and the check
* also fails.
*/
@@ -229,24 +228,25 @@ int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen,
good &= constant_time_ge(tlen, mlen);
/*
- * Even though we can't fake result's length, we can pretend copying
- * |tlen| bytes where |mlen| bytes would be real. Last |tlen| of |num|
- * bytes are viewed as circular buffer with start at |tlen|-|mlen'|,
- * where |mlen'| is "saturated" |mlen| value. Deducing information
- * about failure or |mlen| would take attacker's ability to observe
- * memory access pattern with byte granularity *as it occurs*. It
- * should be noted that failure is indistinguishable from normal
- * operation if |tlen| is fixed by protocol.
+ * Move the result in-place by |num|-11-|mlen| bytes to the left.
+ * Then if |good| move |mlen| bytes from |em|+11 to |to|.
+ * Otherwise leave |to| unchanged.
+ * Copy the memory back in a way that does not reveal the size of
+ * the data being copied via a timing side channel. This requires copying
+ * parts of the buffer multiple times based on the bits set in the real
+ * length. Clear bits do a non-copy with identical access pattern.
+ * The loop below has overall complexity of O(N*log(N)).
*/
- tlen = constant_time_select_int(constant_time_lt(num, tlen), num, tlen);
- msg_index = constant_time_select_int(good, msg_index, num - tlen);
- mlen = num - msg_index;
- for (from += msg_index, mask = good, i = 0; i < tlen; i++) {
- unsigned int equals = constant_time_eq(i, mlen);
-
- from -= tlen & equals; /* if (i == mlen) rewind */
- mask &= mask ^ equals; /* if (i == mlen) mask = 0 */
- to[i] = constant_time_select_8(mask, from[i], to[i]);
+ tlen = constant_time_select_int(constant_time_lt(num - 11, tlen),
+ num - 11, tlen);
+ for (msg_index = 1; msg_index < num - 11; msg_index <<= 1) {
+ mask = ~constant_time_eq(msg_index & (num - 11 - mlen), 0);
+ for (i = 11; i < num - msg_index; i++)
+ em[i] = constant_time_select_8(mask, em[i + msg_index], em[i]);
+ }
+ for (i = 0; i < tlen; i++) {
+ mask = good & constant_time_lt(i, mlen);
+ to[i] = constant_time_select_8(mask, em[i + 11], to[i]);
}
OPENSSL_clear_free(em, num);
diff --git a/freebsd/crypto/openssl/crypto/rsa/rsa_pmeth.c b/freebsd/crypto/openssl/crypto/rsa/rsa_pmeth.c
index d0992e90..0c305e84 100644
--- a/freebsd/crypto/openssl/crypto/rsa/rsa_pmeth.c
+++ b/freebsd/crypto/openssl/crypto/rsa/rsa_pmeth.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -9,6 +9,8 @@
* https://www.openssl.org/source/license.html
*/
+#include "internal/constant_time_locl.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1t.h>
@@ -56,7 +58,7 @@ static int pkey_rsa_init(EVP_PKEY_CTX *ctx)
if (rctx == NULL)
return 0;
- rctx->nbits = 1024;
+ rctx->nbits = 2048;
rctx->primes = RSA_DEFAULT_PRIME_NUM;
if (pkey_ctx_is_pss(ctx))
rctx->pad_mode = RSA_PKCS1_PSS_PADDING;
@@ -342,10 +344,9 @@ static int pkey_rsa_decrypt(EVP_PKEY_CTX *ctx,
ret = RSA_private_decrypt(inlen, in, out, ctx->pkey->pkey.rsa,
rctx->pad_mode);
}
- if (ret < 0)
- return ret;
- *outlen = ret;
- return 1;
+ *outlen = constant_time_select_s(constant_time_msb_s(ret), *outlen, ret);
+ ret = constant_time_select_int(constant_time_msb(ret), ret, 1);
+ return ret;
}
static int check_padding_md(const EVP_MD *md, int padding)
diff --git a/freebsd/crypto/openssl/crypto/rsa/rsa_ssl.c b/freebsd/crypto/openssl/crypto/rsa/rsa_ssl.c
index 9b0edb3f..b5d91c90 100644
--- a/freebsd/crypto/openssl/crypto/rsa/rsa_ssl.c
+++ b/freebsd/crypto/openssl/crypto/rsa/rsa_ssl.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -57,7 +57,7 @@ int RSA_padding_add_SSLv23(unsigned char *to, int tlen,
/*
* Copy of RSA_padding_check_PKCS1_type_2 with a twist that rejects padding
- * if nul delimiter is preceded by 8 consecutive 0x03 bytes. It also
+ * if nul delimiter is not preceded by 8 consecutive 0x03 bytes. It also
* preserves error code reporting for backward compatibility.
*/
int RSA_padding_check_SSLv23(unsigned char *to, int tlen,
@@ -69,7 +69,10 @@ int RSA_padding_check_SSLv23(unsigned char *to, int tlen,
unsigned int good, found_zero_byte, mask, threes_in_row;
int zero_index = 0, msg_index, mlen = -1, err;
- if (flen < 10) {
+ if (tlen <= 0 || flen <= 0)
+ return -1;
+
+ if (flen > num || num < 11) {
RSAerr(RSA_F_RSA_PADDING_CHECK_SSLV23, RSA_R_DATA_TOO_SMALL);
return -1;
}
@@ -91,10 +94,9 @@ int RSA_padding_check_SSLv23(unsigned char *to, int tlen,
from -= 1 & mask;
*--em = *from & mask;
}
- from = em;
- good = constant_time_is_zero(from[0]);
- good &= constant_time_eq(from[1], 2);
+ good = constant_time_is_zero(em[0]);
+ good &= constant_time_eq(em[1], 2);
err = constant_time_select_int(good, 0, RSA_R_BLOCK_TYPE_IS_NOT_02);
mask = ~good;
@@ -102,18 +104,18 @@ int RSA_padding_check_SSLv23(unsigned char *to, int tlen,
found_zero_byte = 0;
threes_in_row = 0;
for (i = 2; i < num; i++) {
- unsigned int equals0 = constant_time_is_zero(from[i]);
+ unsigned int equals0 = constant_time_is_zero(em[i]);
zero_index = constant_time_select_int(~found_zero_byte & equals0,
i, zero_index);
found_zero_byte |= equals0;
threes_in_row += 1 & ~found_zero_byte;
- threes_in_row &= found_zero_byte | constant_time_eq(from[i], 3);
+ threes_in_row &= found_zero_byte | constant_time_eq(em[i], 3);
}
/*
- * PS must be at least 8 bytes long, and it starts two bytes into |from|.
+ * PS must be at least 8 bytes long, and it starts two bytes into |em|.
* If we never found a 0-byte, then |zero_index| is 0 and the check
* also fails.
*/
@@ -122,7 +124,7 @@ int RSA_padding_check_SSLv23(unsigned char *to, int tlen,
RSA_R_NULL_BEFORE_BLOCK_MISSING);
mask = ~good;
- good &= constant_time_lt(threes_in_row, 8);
+ good &= constant_time_ge(threes_in_row, 8);
err = constant_time_select_int(mask | good, err,
RSA_R_SSLV3_ROLLBACK_ATTACK);
mask = ~good;
@@ -141,24 +143,25 @@ int RSA_padding_check_SSLv23(unsigned char *to, int tlen,
err = constant_time_select_int(mask | good, err, RSA_R_DATA_TOO_LARGE);
/*
- * Even though we can't fake result's length, we can pretend copying
- * |tlen| bytes where |mlen| bytes would be real. Last |tlen| of |num|
- * bytes are viewed as circular buffer with start at |tlen|-|mlen'|,
- * where |mlen'| is "saturated" |mlen| value. Deducing information
- * about failure or |mlen| would take attacker's ability to observe
- * memory access pattern with byte granularity *as it occurs*. It
- * should be noted that failure is indistinguishable from normal
- * operation if |tlen| is fixed by protocol.
+ * Move the result in-place by |num|-11-|mlen| bytes to the left.
+ * Then if |good| move |mlen| bytes from |em|+11 to |to|.
+ * Otherwise leave |to| unchanged.
+ * Copy the memory back in a way that does not reveal the size of
+ * the data being copied via a timing side channel. This requires copying
+ * parts of the buffer multiple times based on the bits set in the real
+ * length. Clear bits do a non-copy with identical access pattern.
+ * The loop below has overall complexity of O(N*log(N)).
*/
- tlen = constant_time_select_int(constant_time_lt(num, tlen), num, tlen);
- msg_index = constant_time_select_int(good, msg_index, num - tlen);
- mlen = num - msg_index;
- for (from += msg_index, mask = good, i = 0; i < tlen; i++) {
- unsigned int equals = constant_time_eq(i, mlen);
-
- from -= tlen & equals; /* if (i == mlen) rewind */
- mask &= mask ^ equals; /* if (i == mlen) mask = 0 */
- to[i] = constant_time_select_8(mask, from[i], to[i]);
+ tlen = constant_time_select_int(constant_time_lt(num - 11, tlen),
+ num - 11, tlen);
+ for (msg_index = 1; msg_index < num - 11; msg_index <<= 1) {
+ mask = ~constant_time_eq(msg_index & (num - 11 - mlen), 0);
+ for (i = 11; i < num - msg_index; i++)
+ em[i] = constant_time_select_8(mask, em[i + msg_index], em[i]);
+ }
+ for (i = 0; i < tlen; i++) {
+ mask = good & constant_time_lt(i, mlen);
+ to[i] = constant_time_select_8(mask, em[i + 11], to[i]);
}
OPENSSL_clear_free(em, num);
diff --git a/freebsd/crypto/openssl/crypto/rsa/rsa_x931g.c b/freebsd/crypto/openssl/crypto/rsa/rsa_x931g.c
index 9435cad8..36857a12 100644
--- a/freebsd/crypto/openssl/crypto/rsa/rsa_x931g.c
+++ b/freebsd/crypto/openssl/crypto/rsa/rsa_x931g.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -135,8 +135,7 @@ int RSA_X931_derive_ex(RSA *rsa, BIGNUM *p1, BIGNUM *p2, BIGNUM *q1,
ret = 1;
err:
- if (ctx)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(ctx);
BN_CTX_free(ctx2);
@@ -190,8 +189,7 @@ int RSA_X931_generate_key_ex(RSA *rsa, int bits, const BIGNUM *e,
ok = 1;
error:
- if (ctx)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(ctx);
if (ok)
diff --git a/freebsd/crypto/openssl/crypto/sha/keccak1600.c b/freebsd/crypto/openssl/crypto/sha/keccak1600.c
index 082810d7..7ab6c6f4 100644
--- a/freebsd/crypto/openssl/crypto/sha/keccak1600.c
+++ b/freebsd/crypto/openssl/crypto/sha/keccak1600.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -80,30 +80,30 @@ static const unsigned char rhotates[5][5] = {
};
static const uint64_t iotas[] = {
- BIT_INTERLEAVE ? 0x0000000000000001U : 0x0000000000000001U,
- BIT_INTERLEAVE ? 0x0000008900000000U : 0x0000000000008082U,
- BIT_INTERLEAVE ? 0x8000008b00000000U : 0x800000000000808aU,
- BIT_INTERLEAVE ? 0x8000808000000000U : 0x8000000080008000U,
- BIT_INTERLEAVE ? 0x0000008b00000001U : 0x000000000000808bU,
- BIT_INTERLEAVE ? 0x0000800000000001U : 0x0000000080000001U,
- BIT_INTERLEAVE ? 0x8000808800000001U : 0x8000000080008081U,
- BIT_INTERLEAVE ? 0x8000008200000001U : 0x8000000000008009U,
- BIT_INTERLEAVE ? 0x0000000b00000000U : 0x000000000000008aU,
- BIT_INTERLEAVE ? 0x0000000a00000000U : 0x0000000000000088U,
- BIT_INTERLEAVE ? 0x0000808200000001U : 0x0000000080008009U,
- BIT_INTERLEAVE ? 0x0000800300000000U : 0x000000008000000aU,
- BIT_INTERLEAVE ? 0x0000808b00000001U : 0x000000008000808bU,
- BIT_INTERLEAVE ? 0x8000000b00000001U : 0x800000000000008bU,
- BIT_INTERLEAVE ? 0x8000008a00000001U : 0x8000000000008089U,
- BIT_INTERLEAVE ? 0x8000008100000001U : 0x8000000000008003U,
- BIT_INTERLEAVE ? 0x8000008100000000U : 0x8000000000008002U,
- BIT_INTERLEAVE ? 0x8000000800000000U : 0x8000000000000080U,
- BIT_INTERLEAVE ? 0x0000008300000000U : 0x000000000000800aU,
- BIT_INTERLEAVE ? 0x8000800300000000U : 0x800000008000000aU,
- BIT_INTERLEAVE ? 0x8000808800000001U : 0x8000000080008081U,
- BIT_INTERLEAVE ? 0x8000008800000000U : 0x8000000000008080U,
- BIT_INTERLEAVE ? 0x0000800000000001U : 0x0000000080000001U,
- BIT_INTERLEAVE ? 0x8000808200000000U : 0x8000000080008008U
+ BIT_INTERLEAVE ? 0x0000000000000001ULL : 0x0000000000000001ULL,
+ BIT_INTERLEAVE ? 0x0000008900000000ULL : 0x0000000000008082ULL,
+ BIT_INTERLEAVE ? 0x8000008b00000000ULL : 0x800000000000808aULL,
+ BIT_INTERLEAVE ? 0x8000808000000000ULL : 0x8000000080008000ULL,
+ BIT_INTERLEAVE ? 0x0000008b00000001ULL : 0x000000000000808bULL,
+ BIT_INTERLEAVE ? 0x0000800000000001ULL : 0x0000000080000001ULL,
+ BIT_INTERLEAVE ? 0x8000808800000001ULL : 0x8000000080008081ULL,
+ BIT_INTERLEAVE ? 0x8000008200000001ULL : 0x8000000000008009ULL,
+ BIT_INTERLEAVE ? 0x0000000b00000000ULL : 0x000000000000008aULL,
+ BIT_INTERLEAVE ? 0x0000000a00000000ULL : 0x0000000000000088ULL,
+ BIT_INTERLEAVE ? 0x0000808200000001ULL : 0x0000000080008009ULL,
+ BIT_INTERLEAVE ? 0x0000800300000000ULL : 0x000000008000000aULL,
+ BIT_INTERLEAVE ? 0x0000808b00000001ULL : 0x000000008000808bULL,
+ BIT_INTERLEAVE ? 0x8000000b00000001ULL : 0x800000000000008bULL,
+ BIT_INTERLEAVE ? 0x8000008a00000001ULL : 0x8000000000008089ULL,
+ BIT_INTERLEAVE ? 0x8000008100000001ULL : 0x8000000000008003ULL,
+ BIT_INTERLEAVE ? 0x8000008100000000ULL : 0x8000000000008002ULL,
+ BIT_INTERLEAVE ? 0x8000000800000000ULL : 0x8000000000000080ULL,
+ BIT_INTERLEAVE ? 0x0000008300000000ULL : 0x000000000000800aULL,
+ BIT_INTERLEAVE ? 0x8000800300000000ULL : 0x800000008000000aULL,
+ BIT_INTERLEAVE ? 0x8000808800000001ULL : 0x8000000080008081ULL,
+ BIT_INTERLEAVE ? 0x8000008800000000ULL : 0x8000000000008080ULL,
+ BIT_INTERLEAVE ? 0x0000800000000001ULL : 0x0000000080000001ULL,
+ BIT_INTERLEAVE ? 0x8000808200000000ULL : 0x8000000080008008ULL
};
#if defined(KECCAK_REF)
diff --git a/freebsd/crypto/openssl/crypto/x509/x509_lu.c b/freebsd/crypto/openssl/crypto/x509/x509_lu.c
index 5343ccfb..42010e62 100644
--- a/freebsd/crypto/openssl/crypto/x509/x509_lu.c
+++ b/freebsd/crypto/openssl/crypto/x509/x509_lu.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -299,6 +299,9 @@ int X509_STORE_CTX_get_by_subject(X509_STORE_CTX *vs, X509_LOOKUP_TYPE type,
if (ctx == NULL)
return 0;
+ stmp.type = X509_LU_NONE;
+ stmp.data.ptr = NULL;
+
CRYPTO_THREAD_write_lock(ctx->lock);
tmp = X509_OBJECT_retrieve_by_subject(ctx->objs, type, name);
CRYPTO_THREAD_unlock(ctx->lock);
diff --git a/freebsd/crypto/openssl/crypto/x509v3/v3_genn.c b/freebsd/crypto/openssl/crypto/x509v3/v3_genn.c
index 7fcc2193..7c78c9ab 100644
--- a/freebsd/crypto/openssl/crypto/x509v3/v3_genn.c
+++ b/freebsd/crypto/openssl/crypto/x509v3/v3_genn.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -145,7 +145,7 @@ void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value)
a->type = type;
}
-void *GENERAL_NAME_get0_value(GENERAL_NAME *a, int *ptype)
+void *GENERAL_NAME_get0_value(const GENERAL_NAME *a, int *ptype)
{
if (ptype)
*ptype = a->type;
@@ -190,7 +190,7 @@ int GENERAL_NAME_set0_othername(GENERAL_NAME *gen,
return 1;
}
-int GENERAL_NAME_get0_otherName(GENERAL_NAME *gen,
+int GENERAL_NAME_get0_otherName(const GENERAL_NAME *gen,
ASN1_OBJECT **poid, ASN1_TYPE **pvalue)
{
if (gen->type != GEN_OTHERNAME)
diff --git a/freebsd/crypto/openssl/e_os.h b/freebsd/crypto/openssl/e_os.h
index 8e6efa96..e9ce6c9c 100644
--- a/freebsd/crypto/openssl/e_os.h
+++ b/freebsd/crypto/openssl/e_os.h
@@ -1,5 +1,5 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -27,10 +27,9 @@
* set this to a comma-separated list of 'random' device files to try out. By
* default, we will try to read at least one of these files
*/
-# if defined(__s390__)
-# define DEVRANDOM "/dev/prandom","/dev/urandom","/dev/hwrng","/dev/random"
-# else
-# define DEVRANDOM "/dev/urandom","/dev/random","/dev/srandom"
+# define DEVRANDOM "/dev/urandom", "/dev/random", "/dev/hwrng", "/dev/srandom"
+# ifdef __linux
+# define DEVRANDOM_WAIT "/dev/random"
# endif
# endif
# if !defined(OPENSSL_NO_EGD) && !defined(DEVRANDOM_EGD)
@@ -39,7 +38,7 @@
* sockets will be tried in the order listed in case accessing the device
* files listed in DEVRANDOM did not return enough randomness.
*/
-# define DEVRANDOM_EGD "/var/run/egd-pool","/dev/egd-pool","/etc/egd-pool","/etc/entropy"
+# define DEVRANDOM_EGD "/var/run/egd-pool", "/dev/egd-pool", "/etc/egd-pool", "/etc/entropy"
# endif
# if defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI)
diff --git a/freebsd/crypto/openssl/engines/e_padlock.c b/freebsd/crypto/openssl/engines/e_padlock.c
index 9688d5f3..98cff372 100644
--- a/freebsd/crypto/openssl/engines/e_padlock.c
+++ b/freebsd/crypto/openssl/engines/e_padlock.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2004-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -43,7 +43,7 @@
*/
# undef COMPILE_HW_PADLOCK
-# if !defined(I386_ONLY) && defined(PADLOCK_ASM)
+# if defined(PADLOCK_ASM)
# define COMPILE_HW_PADLOCK
# ifdef OPENSSL_NO_DYNAMIC_ENGINE
static ENGINE *ENGINE_padlock(void);
@@ -150,7 +150,7 @@ static int padlock_init(ENGINE *e)
* This stuff is needed if this ENGINE is being compiled into a
* self-contained shared-library.
*/
-# ifdef DYNAMIC_ENGINE
+# ifndef OPENSSL_NO_DYNAMIC_ENGINE
static int padlock_bind_fn(ENGINE *e, const char *id)
{
if (id && (strcmp(id, padlock_id) != 0)) {
@@ -166,7 +166,7 @@ static int padlock_bind_fn(ENGINE *e, const char *id)
IMPLEMENT_DYNAMIC_CHECK_FN()
IMPLEMENT_DYNAMIC_BIND_FN(padlock_bind_fn)
-# endif /* DYNAMIC_ENGINE */
+# endif /* !OPENSSL_NO_DYNAMIC_ENGINE */
/* ===== Here comes the "real" engine ===== */
/* Some AES-related constants */
diff --git a/freebsd/crypto/openssl/include/internal/dsoerr.h b/freebsd/crypto/openssl/include/internal/dsoerr.h
index a54a1854..0edf277f 100644
--- a/freebsd/crypto/openssl/include/internal/dsoerr.h
+++ b/freebsd/crypto/openssl/include/internal/dsoerr.h
@@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -13,11 +13,9 @@
# include <openssl/opensslconf.h>
-# ifndef OPENSSL_NO_DSO
-
-# ifdef __cplusplus
+# ifdef __cplusplus
extern "C"
-# endif
+# endif
int ERR_load_DSO_strings(void);
/*
@@ -79,5 +77,4 @@ int ERR_load_DSO_strings(void);
# define DSO_R_UNLOAD_FAILED 107
# define DSO_R_UNSUPPORTED 108
-# endif
#endif
diff --git a/freebsd/crypto/openssl/include/internal/refcount.h b/freebsd/crypto/openssl/include/internal/refcount.h
index 75d70a64..d2364c62 100644
--- a/freebsd/crypto/openssl/include/internal/refcount.h
+++ b/freebsd/crypto/openssl/include/internal/refcount.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -79,7 +79,7 @@ static __inline__ int CRYPTO_DOWN_REF(int *val, int *ret, void *lock)
typedef volatile int CRYPTO_REF_COUNT;
-# if (defined(_M_ARM) && _M_ARM>=7) || defined(_M_ARM64)
+# if (defined(_M_ARM) && _M_ARM>=7 && !defined(_WIN32_WCE)) || defined(_M_ARM64)
# include <intrin.h>
# if defined(_M_ARM64) && !defined(_ARM_BARRIER_ISH)
# define _ARM_BARRIER_ISH _ARM64_BARRIER_ISH
@@ -99,7 +99,17 @@ static __inline int CRYPTO_DOWN_REF(volatile int *val, int *ret, void *lock)
return 1;
}
# else
-# pragma intrinsic(_InterlockedExchangeAdd)
+# if !defined(_WIN32_WCE)
+# pragma intrinsic(_InterlockedExchangeAdd)
+# else
+# if _WIN32_WCE >= 0x600
+ extern long __cdecl _InterlockedExchangeAdd(long volatile*, long);
+# else
+ // under Windows CE we still have old-style Interlocked* functions
+ extern long __cdecl InterlockedExchangeAdd(long volatile*, long);
+# define _InterlockedExchangeAdd InterlockedExchangeAdd
+# endif
+# endif
static __inline int CRYPTO_UP_REF(volatile int *val, int *ret, void *lock)
{
diff --git a/freebsd/crypto/openssl/include/internal/tsan_assist.h b/freebsd/crypto/openssl/include/internal/tsan_assist.h
index 38ba0c7e..d41ebb34 100644
--- a/freebsd/crypto/openssl/include/internal/tsan_assist.h
+++ b/freebsd/crypto/openssl/include/internal/tsan_assist.h
@@ -77,7 +77,7 @@
#elif defined(_MSC_VER) && _MSC_VER>=1200 \
&& (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64) || \
- defined(_M_ARM64) || (defined(_M_ARM) && _M_ARM >= 7))
+ defined(_M_ARM64) || (defined(_M_ARM) && _M_ARM >= 7 && !defined(_WIN32_WCE)))
/*
* There is subtle dependency on /volatile:<iso|ms> command-line option.
* "ms" implies same semantic as memory_order_acquire for loads and
diff --git a/freebsd/crypto/openssl/include/openssl/err.h b/freebsd/crypto/openssl/include/openssl/err.h
index 6cae1a36..b49f8812 100644
--- a/freebsd/crypto/openssl/include/openssl/err.h
+++ b/freebsd/crypto/openssl/include/openssl/err.h
@@ -1,5 +1,5 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -37,6 +37,7 @@ extern "C" {
# define ERR_TXT_STRING 0x02
# define ERR_FLAG_MARK 0x01
+# define ERR_FLAG_CLEAR 0x02
# define ERR_NUM_ERRORS 16
typedef struct err_state_st {
diff --git a/freebsd/crypto/openssl/include/openssl/evp.h b/freebsd/crypto/openssl/include/openssl/evp.h
index 9f05b5a3..dd1117d0 100644
--- a/freebsd/crypto/openssl/include/openssl/evp.h
+++ b/freebsd/crypto/openssl/include/openssl/evp.h
@@ -995,6 +995,7 @@ int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len);
int EVP_PKEY_set_alias_type(EVP_PKEY *pkey, int type);
# ifndef OPENSSL_NO_ENGINE
int EVP_PKEY_set1_engine(EVP_PKEY *pkey, ENGINE *e);
+ENGINE *EVP_PKEY_get0_engine(const EVP_PKEY *pkey);
# endif
int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key);
void *EVP_PKEY_get0(const EVP_PKEY *pkey);
diff --git a/freebsd/crypto/openssl/include/openssl/obj_mac.h b/freebsd/crypto/openssl/include/openssl/obj_mac.h
index 31fad464..47dafe48 100644
--- a/freebsd/crypto/openssl/include/openssl/obj_mac.h
+++ b/freebsd/crypto/openssl/include/openssl/obj_mac.h
@@ -4280,7 +4280,7 @@
#define SN_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 "id-tc26-wrap-gostr3412-2015-kuznyechik-kexp15"
#define NID_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 1183
-#define OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 OBJ_id_tc26_wrap_gostr3412_2015_magma,1L
+#define OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik,1L
#define SN_id_tc26_constants "id-tc26-constants"
#define NID_id_tc26_constants 994
diff --git a/freebsd/crypto/openssl/include/openssl/ocsp.h b/freebsd/crypto/openssl/include/openssl/ocsp.h
index 0a17166b..8582fe1e 100644
--- a/freebsd/crypto/openssl/include/openssl/ocsp.h
+++ b/freebsd/crypto/openssl/include/openssl/ocsp.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -229,8 +229,8 @@ int OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs,
int OCSP_parse_url(const char *url, char **phost, char **pport, char **ppath,
int *pssl);
-int OCSP_id_issuer_cmp(OCSP_CERTID *a, OCSP_CERTID *b);
-int OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b);
+int OCSP_id_issuer_cmp(const OCSP_CERTID *a, const OCSP_CERTID *b);
+int OCSP_id_cmp(const OCSP_CERTID *a, const OCSP_CERTID *b);
int OCSP_request_onereq_count(OCSP_REQUEST *req);
OCSP_ONEREQ *OCSP_request_onereq_get0(OCSP_REQUEST *req, int i);
diff --git a/freebsd/crypto/openssl/include/openssl/opensslv.h b/freebsd/crypto/openssl/include/openssl/opensslv.h
index e1e4f224..e4f3ffe9 100644
--- a/freebsd/crypto/openssl/include/openssl/opensslv.h
+++ b/freebsd/crypto/openssl/include/openssl/opensslv.h
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -39,8 +39,8 @@ extern "C" {
* (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for
* major minor fix final patch/beta)
*/
-# define OPENSSL_VERSION_NUMBER 0x1010102fL
-# define OPENSSL_VERSION_TEXT "OpenSSL 1.1.1b-freebsd 26 Feb 2019"
+# define OPENSSL_VERSION_NUMBER 0x1010103fL
+# define OPENSSL_VERSION_TEXT "OpenSSL 1.1.1c-freebsd 28 May 2019"
/*-
* The macros below are to be used for shared library (.so, .dll, ...)
diff --git a/freebsd/crypto/openssl/include/openssl/ssl.h b/freebsd/crypto/openssl/include/openssl/ssl.h
index 48e1152a..f93dc68f 100644
--- a/freebsd/crypto/openssl/include/openssl/ssl.h
+++ b/freebsd/crypto/openssl/include/openssl/ssl.h
@@ -2139,7 +2139,7 @@ size_t SSL_CTX_get_num_tickets(const SSL_CTX *ctx);
# define SSL_cache_hit(s) SSL_session_reused(s)
# endif
-__owur int SSL_session_reused(SSL *s);
+__owur int SSL_session_reused(const SSL *s);
__owur int SSL_is_server(const SSL *s);
__owur __owur SSL_CONF_CTX *SSL_CONF_CTX_new(void);
diff --git a/freebsd/crypto/openssl/include/openssl/x509v3.h b/freebsd/crypto/openssl/include/openssl/x509v3.h
index fe1791c6..9ea20275 100644
--- a/freebsd/crypto/openssl/include/openssl/x509v3.h
+++ b/freebsd/crypto/openssl/include/openssl/x509v3.h
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -497,10 +497,10 @@ DECLARE_ASN1_FUNCTIONS(OTHERNAME)
DECLARE_ASN1_FUNCTIONS(EDIPARTYNAME)
int OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b);
void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value);
-void *GENERAL_NAME_get0_value(GENERAL_NAME *a, int *ptype);
+void *GENERAL_NAME_get0_value(const GENERAL_NAME *a, int *ptype);
int GENERAL_NAME_set0_othername(GENERAL_NAME *gen,
ASN1_OBJECT *oid, ASN1_TYPE *value);
-int GENERAL_NAME_get0_otherName(GENERAL_NAME *gen,
+int GENERAL_NAME_get0_otherName(const GENERAL_NAME *gen,
ASN1_OBJECT **poid, ASN1_TYPE **pvalue);
char *i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method,
diff --git a/freebsd/crypto/openssl/ssl/ssl_lib.c b/freebsd/crypto/openssl/ssl/ssl_lib.c
index 1516f492..9c2c9dac 100644
--- a/freebsd/crypto/openssl/ssl/ssl_lib.c
+++ b/freebsd/crypto/openssl/ssl/ssl_lib.c
@@ -4480,7 +4480,7 @@ int ssl_handshake_hash(SSL *s, unsigned char *out, size_t outlen,
return ret;
}
-int SSL_session_reused(SSL *s)
+int SSL_session_reused(const SSL *s)
{
return s->hit;
}
@@ -5072,6 +5072,11 @@ int SSL_client_hello_get1_extensions_present(SSL *s, int **out, size_t *outlen)
if (ext->present)
num++;
}
+ if (num == 0) {
+ *out = NULL;
+ *outlen = 0;
+ return 1;
+ }
if ((present = OPENSSL_malloc(sizeof(*present) * num)) == NULL) {
SSLerr(SSL_F_SSL_CLIENT_HELLO_GET1_EXTENSIONS_PRESENT,
ERR_R_MALLOC_FAILURE);
diff --git a/freebsd/crypto/openssl/ssl/ssl_locl.h b/freebsd/crypto/openssl/ssl/ssl_locl.h
index f326399e..0cf3893e 100644
--- a/freebsd/crypto/openssl/ssl/ssl_locl.h
+++ b/freebsd/crypto/openssl/ssl/ssl_locl.h
@@ -574,7 +574,6 @@ struct ssl_session_st {
/* Session lifetime hint in seconds */
unsigned long tick_lifetime_hint;
uint32_t tick_age_add;
- int tick_identity;
/* Max number of bytes that can be sent as early data */
uint32_t max_early_data;
/* The ALPN protocol selected for this session */
@@ -1356,6 +1355,13 @@ struct ssl_st {
* as this extension is optional on server side.
*/
uint8_t max_fragment_len_mode;
+
+ /*
+ * On the client side the number of ticket identities we sent in the
+ * ClientHello. On the server side the identity of the ticket we
+ * selected.
+ */
+ int tick_identity;
} ext;
/*
@@ -1509,7 +1515,7 @@ typedef struct cert_pkey_st CERT_PKEY;
* CERT_PKEY entries
*/
typedef struct {
- int nid; /* NID of pubic key algorithm */
+ int nid; /* NID of public key algorithm */
uint32_t amask; /* authmask corresponding to key type */
} SSL_CERT_LOOKUP;
@@ -2052,9 +2058,6 @@ typedef enum downgrade_en {
#define TLSEXT_KEX_MODE_FLAG_KE 1
#define TLSEXT_KEX_MODE_FLAG_KE_DHE 2
-/* An invalid index into the TLSv1.3 PSK identities */
-#define TLSEXT_PSK_BAD_IDENTITY -1
-
#define SSL_USE_PSS(s) (s->s3->tmp.peer_sigalg != NULL && \
s->s3->tmp.peer_sigalg->sig == EVP_PKEY_RSA_PSS)
diff --git a/freebsd/crypto/openssl/ssl/statem/extensions.c b/freebsd/crypto/openssl/ssl/statem/extensions.c
index f105ea78..91c3fd56 100644
--- a/freebsd/crypto/openssl/ssl/statem/extensions.c
+++ b/freebsd/crypto/openssl/ssl/statem/extensions.c
@@ -991,7 +991,6 @@ static int final_server_name(SSL *s, unsigned int context, int sent)
ss->ext.ticklen = 0;
ss->ext.tick_lifetime_hint = 0;
ss->ext.tick_age_add = 0;
- ss->ext.tick_identity = 0;
if (!ssl_generate_session_id(s, ss)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME,
ERR_R_INTERNAL_ERROR);
@@ -1648,7 +1647,6 @@ static int final_early_data(SSL *s, unsigned int context, int sent)
if (s->max_early_data == 0
|| !s->hit
- || s->session->ext.tick_identity != 0
|| s->early_data_state != SSL_EARLY_DATA_ACCEPTING
|| !s->ext.early_data_ok
|| s->hello_retry_request != SSL_HRR_NONE
diff --git a/freebsd/crypto/openssl/ssl/statem/extensions_clnt.c b/freebsd/crypto/openssl/ssl/statem/extensions_clnt.c
index a64d5367..ead0dde9 100644
--- a/freebsd/crypto/openssl/ssl/statem/extensions_clnt.c
+++ b/freebsd/crypto/openssl/ssl/statem/extensions_clnt.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -995,7 +995,7 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
const EVP_MD *handmd = NULL, *mdres = NULL, *mdpsk = NULL;
int dores = 0;
- s->session->ext.tick_identity = TLSEXT_PSK_BAD_IDENTITY;
+ s->ext.tick_identity = 0;
/*
* Note: At this stage of the code we only support adding a single
@@ -1085,6 +1085,7 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
agems += s->session->ext.tick_age_add;
reshashsize = EVP_MD_size(mdres);
+ s->ext.tick_identity++;
dores = 1;
}
@@ -1144,6 +1145,7 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
+ s->ext.tick_identity++;
}
if (!WPACKET_close(pkt)
@@ -1182,11 +1184,6 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
return EXT_RETURN_FAIL;
}
- if (dores)
- s->session->ext.tick_identity = 0;
- if (s->psksession != NULL)
- s->psksession->ext.tick_identity = (dores ? 1 : 0);
-
return EXT_RETURN_SENT;
#else
return EXT_RETURN_NOT_SENT;
@@ -1929,8 +1926,7 @@ int tls_parse_stoc_early_data(SSL *s, PACKET *pkt, unsigned int context,
}
if (!s->ext.early_data_ok
- || !s->hit
- || s->session->ext.tick_identity != 0) {
+ || !s->hit) {
/*
* If we get here then we didn't send early data, or we didn't resume
* using the first identity, or the SNI/ALPN is not consistent so the
@@ -1958,17 +1954,28 @@ int tls_parse_stoc_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
return 0;
}
- if (s->session->ext.tick_identity == (int)identity) {
+ if (identity >= (unsigned int)s->ext.tick_identity) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_PSK,
+ SSL_R_BAD_PSK_IDENTITY);
+ return 0;
+ }
+
+ /*
+ * Session resumption tickets are always sent before PSK tickets. If the
+ * ticket index is 0 then it must be for a session resumption ticket if we
+ * sent two tickets, or if we didn't send a PSK ticket.
+ */
+ if (identity == 0 && (s->psksession == NULL || s->ext.tick_identity == 2)) {
s->hit = 1;
SSL_SESSION_free(s->psksession);
s->psksession = NULL;
return 1;
}
- if (s->psksession == NULL
- || s->psksession->ext.tick_identity != (int)identity) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_PSK,
- SSL_R_BAD_PSK_IDENTITY);
+ if (s->psksession == NULL) {
+ /* Should never happen */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_PSK,
+ ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -1987,6 +1994,9 @@ int tls_parse_stoc_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
s->session = s->psksession;
s->psksession = NULL;
s->hit = 1;
+ /* Early data is only allowed if we used the first ticket */
+ if (identity != 0)
+ s->ext.early_data_ok = 0;
#endif
return 1;
diff --git a/freebsd/crypto/openssl/ssl/statem/extensions_srvr.c b/freebsd/crypto/openssl/ssl/statem/extensions_srvr.c
index d6907198..a2c2ebe4 100644
--- a/freebsd/crypto/openssl/ssl/statem/extensions_srvr.c
+++ b/freebsd/crypto/openssl/ssl/statem/extensions_srvr.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -1276,7 +1276,7 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
goto err;
}
- sess->ext.tick_identity = id;
+ s->ext.tick_identity = id;
SSL_SESSION_free(s->session);
s->session = sess;
@@ -1950,7 +1950,7 @@ EXT_RETURN tls_construct_stoc_psk(SSL *s, WPACKET *pkt, unsigned int context,
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_psk)
|| !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_put_bytes_u16(pkt, s->session->ext.tick_identity)
+ || !WPACKET_put_bytes_u16(pkt, s->ext.tick_identity)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_STOC_PSK, ERR_R_INTERNAL_ERROR);
diff --git a/freebsd/crypto/openssl/ssl/statem/statem_clnt.c b/freebsd/crypto/openssl/ssl/statem/statem_clnt.c
index 5ddbebd3..ec82e6d3 100644
--- a/freebsd/crypto/openssl/ssl/statem/statem_clnt.c
+++ b/freebsd/crypto/openssl/ssl/statem/statem_clnt.c
@@ -1615,10 +1615,7 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
* so the PAC-based session secret is always preserved. It'll be
* overwritten if the server refuses resumption.
*/
- if (s->session->session_id_length > 0
- || (SSL_IS_TLS13(s)
- && s->session->ext.tick_identity
- != TLSEXT_PSK_BAD_IDENTITY)) {
+ if (s->session->session_id_length > 0) {
tsan_counter(&s->session_ctx->stats.sess_miss);
if (!ssl_get_new_session(s, 0)) {
/* SSLfatal() already called */
diff --git a/freebsd/crypto/openssl/ssl/statem/statem_srvr.c b/freebsd/crypto/openssl/ssl/statem/statem_srvr.c
index f00623d6..de1a6c77 100644
--- a/freebsd/crypto/openssl/ssl/statem/statem_srvr.c
+++ b/freebsd/crypto/openssl/ssl/statem/statem_srvr.c
@@ -777,6 +777,10 @@ static ossl_inline int conn_is_closed(void)
case ECONNRESET:
return 1;
#endif
+#if defined(WSAECONNRESET)
+ case WSAECONNRESET:
+ return 1;
+#endif
default:
return 0;
}
diff --git a/freebsd/lib/libc/include/libc_private.h b/freebsd/lib/libc/include/libc_private.h
index 8e78f556..2231241f 100644
--- a/freebsd/lib/libc/include/libc_private.h
+++ b/freebsd/lib/libc/include/libc_private.h
@@ -239,6 +239,7 @@ enum {
INTERPOS_map_stacks_exec,
INTERPOS_fdatasync,
INTERPOS_clock_nanosleep,
+ INTERPOS_distribute_static_tls,
INTERPOS_MAX
};
@@ -417,6 +418,8 @@ struct dl_phdr_info;
int __elf_phdr_match_addr(struct dl_phdr_info *, void *);
void __init_elf_aux_vector(void);
void __libc_map_stacks_exec(void);
+void __libc_distribute_static_tls(__size_t, void *, __size_t, __size_t);
+__uintptr_t __libc_static_tls_base(__size_t);
void _pthread_cancel_enter(int);
void _pthread_cancel_leave(int);
diff --git a/freebsd/lib/libc/net/getnameinfo.c b/freebsd/lib/libc/net/getnameinfo.c
index 219e149d..8fa00b24 100644
--- a/freebsd/lib/libc/net/getnameinfo.c
+++ b/freebsd/lib/libc/net/getnameinfo.c
@@ -226,10 +226,8 @@ getnameinfo_inet(const struct afd *afd,
case AF_INET:
v4a = (u_int32_t)
ntohl(((const struct sockaddr_in *)sa)->sin_addr.s_addr);
- if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
- flags |= NI_NUMERICHOST;
- v4a >>= IN_CLASSA_NSHIFT;
- if (v4a == 0)
+ if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a) ||
+ IN_ZERONET(v4a))
flags |= NI_NUMERICHOST;
break;
#ifdef INET6
diff --git a/freebsd/sbin/ifconfig/ifconfig.c b/freebsd/sbin/ifconfig/ifconfig.c
index c0907866..d27dcdc2 100644
--- a/freebsd/sbin/ifconfig/ifconfig.c
+++ b/freebsd/sbin/ifconfig/ifconfig.c
@@ -86,6 +86,7 @@ static const char rcsid[] =
#ifdef JAIL
#include <jail.h>
#endif
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -148,6 +149,31 @@ struct ifa_order_elt {
TAILQ_HEAD(ifa_queue, ifa_order_elt);
+static struct module_map_entry {
+ const char *ifname;
+ const char *kldname;
+} module_map[] = {
+ {
+ .ifname = "vmnet",
+ .kldname = "if_tap",
+ },
+ {
+ .ifname = "ipsec",
+ .kldname = "ipsec",
+ },
+ {
+ /*
+ * This mapping exists because there is a conflicting enc module
+ * in CAM. ifconfig's guessing behavior will attempt to match
+ * the ifname to a module as well as if_${ifname} and clash with
+ * CAM enc. This is an assertion of the correct module to load.
+ */
+ .ifname = "enc",
+ .kldname = "if_enc",
+ },
+};
+
+
void
opt_register(struct option *p)
{
@@ -1499,9 +1525,11 @@ ifmaybeload(const char *name)
#ifndef __rtems__
#define MOD_PREFIX_LEN 3 /* "if_" */
struct module_stat mstat;
- int fileid, modid;
+ int i, fileid, modid;
char ifkind[IFNAMSIZ + MOD_PREFIX_LEN], ifname[IFNAMSIZ], *dp;
const char *cp;
+ struct module_map_entry *mme;
+ bool found;
/* loading suppressed by the user */
if (noload)
@@ -1515,9 +1543,24 @@ ifmaybeload(const char *name)
break;
}
- /* turn interface and unit into module name */
- strlcpy(ifkind, "if_", sizeof(ifkind));
- strlcat(ifkind, ifname, sizeof(ifkind));
+ /* Either derive it from the map or guess otherwise */
+ *ifkind = '\0';
+ found = false;
+ for (i = 0; i < nitems(module_map); ++i) {
+ mme = &module_map[i];
+ if (strcmp(mme->ifname, ifname) == 0) {
+ strlcpy(ifkind, mme->kldname, sizeof(ifkind));
+ found = true;
+ break;
+ }
+ }
+
+ /* We didn't have an alias for it... we'll guess. */
+ if (!found) {
+ /* turn interface and unit into module name */
+ strlcpy(ifkind, "if_", sizeof(ifkind));
+ strlcat(ifkind, ifname, sizeof(ifkind));
+ }
/* scan files in kernel */
mstat.version = sizeof(struct module_stat);
@@ -1533,8 +1576,12 @@ ifmaybeload(const char *name)
} else {
cp = mstat.name;
}
- /* already loaded? */
- if (strcmp(ifname, cp) == 0 ||
+ /*
+ * Is it already loaded? Don't compare with ifname if
+ * we were specifically told which kld to use. Doing
+ * so could lead to conflicts not trivially solved.
+ */
+ if ((!found && strcmp(ifname, cp) == 0) ||
strcmp(ifkind, cp) == 0)
return;
}
diff --git a/freebsd/sbin/ifconfig/ifgre.c b/freebsd/sbin/ifconfig/ifgre.c
index 2adc6d76..092e70c2 100644
--- a/freebsd/sbin/ifconfig/ifgre.c
+++ b/freebsd/sbin/ifconfig/ifgre.c
@@ -56,15 +56,16 @@ __FBSDID("$FreeBSD$");
#include "rtems-bsd-ifconfig-ifgre-data.h"
#endif /* __rtems__ */
-#define GREBITS "\020\01ENABLE_CSUM\02ENABLE_SEQ"
+#define GREBITS "\020\01ENABLE_CSUM\02ENABLE_SEQ\03UDPENCAP"
static void gre_status(int s);
static void
gre_status(int s)
{
- uint32_t opts = 0;
+ uint32_t opts, port;
+ opts = 0;
ifr.ifr_data = (caddr_t)&opts;
if (ioctl(s, GREGKEY, &ifr) == 0)
if (opts != 0)
@@ -72,6 +73,11 @@ gre_status(int s)
opts = 0;
if (ioctl(s, GREGOPTS, &ifr) != 0 || opts == 0)
return;
+
+ port = 0;
+ ifr.ifr_data = (caddr_t)&port;
+ if (ioctl(s, GREGPORT, &ifr) == 0 && port != 0)
+ printf("\tudpport: %u\n", port);
printb("\toptions", opts, GREBITS);
putchar('\n');
}
@@ -89,6 +95,18 @@ setifgrekey(const char *val, int dummy __unused, int s,
}
static void
+setifgreport(const char *val, int dummy __unused, int s,
+ const struct afswtch *afp)
+{
+ uint32_t udpport = strtol(val, NULL, 0);
+
+ strlcpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
+ ifr.ifr_data = (caddr_t)&udpport;
+ if (ioctl(s, GRESPORT, (caddr_t)&ifr) < 0)
+ warn("ioctl (set udpport)");
+}
+
+static void
setifgreopts(const char *val, int d, int s, const struct afswtch *afp)
{
uint32_t opts;
@@ -113,10 +131,13 @@ setifgreopts(const char *val, int d, int s, const struct afswtch *afp)
static struct cmd gre_cmds[] = {
DEF_CMD_ARG("grekey", setifgrekey),
+ DEF_CMD_ARG("udpport", setifgreport),
DEF_CMD("enable_csum", GRE_ENABLE_CSUM, setifgreopts),
DEF_CMD("-enable_csum",-GRE_ENABLE_CSUM,setifgreopts),
DEF_CMD("enable_seq", GRE_ENABLE_SEQ, setifgreopts),
DEF_CMD("-enable_seq",-GRE_ENABLE_SEQ, setifgreopts),
+ DEF_CMD("udpencap", GRE_UDPENCAP, setifgreopts),
+ DEF_CMD("-udpencap",-GRE_UDPENCAP, setifgreopts),
};
static struct afswtch af_gre = {
.af_name = "af_gre",
diff --git a/freebsd/sbin/pfctl/pfctl_optimize.c b/freebsd/sbin/pfctl/pfctl_optimize.c
index cbf94e80..02a1018c 100644
--- a/freebsd/sbin/pfctl/pfctl_optimize.c
+++ b/freebsd/sbin/pfctl/pfctl_optimize.c
@@ -1549,14 +1549,24 @@ superblock_inclusive(struct superblock *block, struct pf_opt_rule *por)
int
interface_group(const char *ifname)
{
+ int s;
+ struct ifgroupreq ifgr;
+
if (ifname == NULL || !ifname[0])
return (0);
- /* Real interfaces must end in a number, interface groups do not */
- if (isdigit(ifname[strlen(ifname) - 1]))
- return (0);
- else
- return (1);
+ s = get_query_socket();
+
+ memset(&ifgr, 0, sizeof(ifgr));
+ strlcpy(ifgr.ifgr_name, ifname, IFNAMSIZ);
+ if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) {
+ if (errno == ENOENT)
+ return (0);
+ else
+ err(1, "SIOCGIFGMEMB");
+ }
+
+ return (1);
}
diff --git a/freebsd/sys/arm/ti/cpsw/if_cpsw.c b/freebsd/sys/arm/ti/cpsw/if_cpsw.c
index 1fbda688..fb61aeb4 100644
--- a/freebsd/sys/arm/ti/cpsw/if_cpsw.c
+++ b/freebsd/sys/arm/ti/cpsw/if_cpsw.c
@@ -84,6 +84,8 @@ __FBSDID("$FreeBSD$");
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/fdt/fdt_common.h>
#ifdef CPSW_ETHERSWITCH
#include <dev/etherswitch/etherswitch.h>
@@ -749,7 +751,7 @@ cpsw_get_fdt_data(struct cpsw_softc *sc, int port)
phandle_t child;
unsigned long mdio_child_addr;
- /* Find any slave with phy_id */
+ /* Find any slave with phy-handle/phy_id */
phy = -1;
vlan = -1;
for (child = OF_child(sc->node); child != 0; child = OF_peer(child)) {
@@ -763,11 +765,15 @@ cpsw_get_fdt_data(struct cpsw_softc *sc, int port)
if (mdio_child_addr != slave_mdio_addr[port])
continue;
- len = OF_getproplen(child, "phy_id");
- if (len / sizeof(pcell_t) == 2) {
- /* Get phy address from fdt */
- if (OF_getencprop(child, "phy_id", phy_id, len) > 0)
- phy = phy_id[1];
+ if (fdt_get_phyaddr(child, NULL, &phy, NULL) != 0){
+ /* Users with old DTB will have phy_id instead */
+ phy = -1;
+ len = OF_getproplen(child, "phy_id");
+ if (len / sizeof(pcell_t) == 2) {
+ /* Get phy address from fdt */
+ if (OF_getencprop(child, "phy_id", phy_id, len) > 0)
+ phy = phy_id[1];
+ }
}
len = OF_getproplen(child, "dual_emac_res_vlan");
diff --git a/freebsd/sys/cam/cam_periph.h b/freebsd/sys/cam/cam_periph.h
index 6eb0084a..b087b872 100644
--- a/freebsd/sys/cam/cam_periph.h
+++ b/freebsd/sys/cam/cam_periph.h
@@ -149,6 +149,7 @@ struct cam_periph {
struct cam_periph_map_info {
int num_bufs_used;
+ void *orig[CAM_PERIPH_MAXMAPS];
struct buf *bp[CAM_PERIPH_MAXMAPS];
};
diff --git a/freebsd/sys/cam/scsi/scsi_all.c b/freebsd/sys/cam/scsi/scsi_all.c
index 1a469f32..d0eb431a 100644
--- a/freebsd/sys/cam/scsi/scsi_all.c
+++ b/freebsd/sys/cam/scsi/scsi_all.c
@@ -3947,7 +3947,7 @@ scsi_set_sense_data_fixed_va(struct scsi_sense_data *sense_data,
}
if (len > sizeof(sense->cmd_spec_info)) {
data += len - sizeof(sense->cmd_spec_info);
- len -= len - sizeof(sense->cmd_spec_info);
+ len = sizeof(sense->cmd_spec_info);
}
bcopy(data, &sense->cmd_spec_info[
sizeof(sense->cmd_spec_info) - len], len);
@@ -4066,6 +4066,10 @@ scsi_get_sense_info(struct scsi_sense_data *sense_data, u_int sense_len,
struct scsi_sense_info *info_desc;
info_desc = (struct scsi_sense_info *)desc;
+
+ if ((info_desc->byte2 & SSD_INFO_VALID) == 0)
+ goto bailout;
+
*info = scsi_8btou64(info_desc->info);
if (signed_info != NULL)
*signed_info = *info;
@@ -4086,6 +4090,9 @@ scsi_get_sense_info(struct scsi_sense_data *sense_data, u_int sense_len,
fru_desc = (struct scsi_sense_fru *)desc;
+ if (fru_desc->fru == 0)
+ goto bailout;
+
*info = fru_desc->fru;
if (signed_info != NULL)
*signed_info = (int8_t)fru_desc->fru;
@@ -4186,10 +4193,9 @@ scsi_get_sks(struct scsi_sense_data *sense_data, u_int sense_len, uint8_t *sks)
if (desc == NULL)
goto bailout;
- /*
- * No need to check the SKS valid bit for descriptor sense.
- * If the descriptor is present, it is valid.
- */
+ if ((desc->sense_key_spec[0] & SSD_SKS_VALID) == 0)
+ goto bailout;
+
bcopy(desc->sense_key_spec, sks, sizeof(desc->sense_key_spec));
break;
}
@@ -4266,9 +4272,6 @@ scsi_get_block_info(struct scsi_sense_data *sense_data, u_int sense_len,
if (SSD_FIXED_IS_PRESENT(sense, sense_len, flags) == 0)
goto bailout;
- if ((sense->flags & SSD_ILI) == 0)
- goto bailout;
-
*block_bits = sense->flags & SSD_ILI;
break;
}
@@ -4322,9 +4325,6 @@ scsi_get_stream_info(struct scsi_sense_data *sense_data, u_int sense_len,
if (SSD_FIXED_IS_PRESENT(sense, sense_len, flags) == 0)
goto bailout;
- if ((sense->flags & (SSD_ILI|SSD_EOM|SSD_FILEMARK)) == 0)
- goto bailout;
-
*stream_bits = sense->flags & (SSD_ILI|SSD_EOM|SSD_FILEMARK);
break;
}
@@ -4366,8 +4366,6 @@ scsi_progress_sbuf(struct sbuf *sb, uint16_t progress)
int
scsi_sks_sbuf(struct sbuf *sb, int sense_key, uint8_t *sks)
{
- if ((sks[0] & SSD_SKS_VALID) == 0)
- return (1);
switch (sense_key) {
case SSD_KEY_ILLEGAL_REQUEST: {
@@ -4464,7 +4462,7 @@ scsi_fru_sbuf(struct sbuf *sb, uint64_t fru)
}
void
-scsi_stream_sbuf(struct sbuf *sb, uint8_t stream_bits, uint64_t info)
+scsi_stream_sbuf(struct sbuf *sb, uint8_t stream_bits)
{
int need_comma;
@@ -4472,6 +4470,7 @@ scsi_stream_sbuf(struct sbuf *sb, uint8_t stream_bits, uint64_t info)
/*
* XXX KDM this needs more descriptive decoding.
*/
+ sbuf_printf(sb, "Stream Command Sense Data: ");
if (stream_bits & SSD_DESC_STREAM_FM) {
sbuf_printf(sb, "Filemark");
need_comma = 1;
@@ -4484,15 +4483,15 @@ scsi_stream_sbuf(struct sbuf *sb, uint8_t stream_bits, uint64_t info)
if (stream_bits & SSD_DESC_STREAM_ILI)
sbuf_printf(sb, "%sILI", (need_comma) ? "," : "");
-
- sbuf_printf(sb, ": Info: %#jx", (uintmax_t) info);
}
void
-scsi_block_sbuf(struct sbuf *sb, uint8_t block_bits, uint64_t info)
+scsi_block_sbuf(struct sbuf *sb, uint8_t block_bits)
{
+
+ sbuf_printf(sb, "Block Command Sense Data: ");
if (block_bits & SSD_DESC_BLOCK_ILI)
- sbuf_printf(sb, "ILI: residue %#jx", (uintmax_t) info);
+ sbuf_printf(sb, "ILI");
}
void
@@ -4505,6 +4504,9 @@ scsi_sense_info_sbuf(struct sbuf *sb, struct scsi_sense_data *sense,
info = (struct scsi_sense_info *)header;
+ if ((info->byte2 & SSD_INFO_VALID) == 0)
+ return;
+
scsi_info_sbuf(sb, cdb, cdb_len, inq_data, scsi_8btou64(info->info));
}
@@ -4533,6 +4535,9 @@ scsi_sense_sks_sbuf(struct sbuf *sb, struct scsi_sense_data *sense,
sks = (struct scsi_sense_sks *)header;
+ if ((sks->sense_key_spec[0] & SSD_SKS_VALID) == 0)
+ return;
+
scsi_extract_sense_len(sense, sense_len, &error_code, &sense_key,
&asc, &ascq, /*show_errors*/ 1);
@@ -4549,6 +4554,9 @@ scsi_sense_fru_sbuf(struct sbuf *sb, struct scsi_sense_data *sense,
fru = (struct scsi_sense_fru *)header;
+ if (fru->fru == 0)
+ return;
+
scsi_fru_sbuf(sb, (uint64_t)fru->fru);
}
@@ -4559,14 +4567,9 @@ scsi_sense_stream_sbuf(struct sbuf *sb, struct scsi_sense_data *sense,
struct scsi_sense_desc_header *header)
{
struct scsi_sense_stream *stream;
- uint64_t info;
stream = (struct scsi_sense_stream *)header;
- info = 0;
-
- scsi_get_sense_info(sense, sense_len, SSD_DESC_INFO, &info, NULL);
-
- scsi_stream_sbuf(sb, stream->byte3, info);
+ scsi_stream_sbuf(sb, stream->byte3);
}
void
@@ -4576,14 +4579,9 @@ scsi_sense_block_sbuf(struct sbuf *sb, struct scsi_sense_data *sense,
struct scsi_sense_desc_header *header)
{
struct scsi_sense_block *block;
- uint64_t info;
block = (struct scsi_sense_block *)header;
- info = 0;
-
- scsi_get_sense_info(sense, sense_len, SSD_DESC_INFO, &info, NULL);
-
- scsi_block_sbuf(sb, block->byte3, info);
+ scsi_block_sbuf(sb, block->byte3);
}
void
@@ -4868,7 +4866,7 @@ scsi_sense_only_sbuf(struct scsi_sense_data *sense, u_int sense_len,
const char *asc_desc;
uint8_t sks[3];
uint64_t val;
- int info_valid;
+ uint8_t bits;
/*
* Get descriptions for the sense key, ASC, and ASCQ. If
@@ -4887,42 +4885,28 @@ scsi_sense_only_sbuf(struct scsi_sense_data *sense, u_int sense_len,
sbuf_printf(sb, " asc:%x,%x (%s)\n", asc, ascq, asc_desc);
/*
- * Get the info field if it is valid.
+ * Print any block or stream device-specific information.
*/
- if (scsi_get_sense_info(sense, sense_len, SSD_DESC_INFO,
- &val, NULL) == 0)
- info_valid = 1;
- else
- info_valid = 0;
-
- if (info_valid != 0) {
- uint8_t bits;
+ if (scsi_get_block_info(sense, sense_len, inq_data,
+ &bits) == 0 && bits != 0) {
+ sbuf_cat(sb, path_str);
+ scsi_block_sbuf(sb, bits);
+ sbuf_printf(sb, "\n");
+ } else if (scsi_get_stream_info(sense, sense_len, inq_data,
+ &bits) == 0 && bits != 0) {
+ sbuf_cat(sb, path_str);
+ scsi_stream_sbuf(sb, bits);
+ sbuf_printf(sb, "\n");
+ }
- /*
- * Determine whether we have any block or stream
- * device-specific information.
- */
- if (scsi_get_block_info(sense, sense_len, inq_data,
- &bits) == 0) {
- sbuf_cat(sb, path_str);
- scsi_block_sbuf(sb, bits, val);
- sbuf_printf(sb, "\n");
- } else if (scsi_get_stream_info(sense, sense_len,
- inq_data, &bits) == 0) {
- sbuf_cat(sb, path_str);
- scsi_stream_sbuf(sb, bits, val);
- sbuf_printf(sb, "\n");
- } else if (val != 0) {
- /*
- * The information field can be valid but 0.
- * If the block or stream bits aren't set,
- * and this is 0, it isn't terribly useful
- * to print it out.
- */
- sbuf_cat(sb, path_str);
- scsi_info_sbuf(sb, cdb, cdb_len, inq_data, val);
- sbuf_printf(sb, "\n");
- }
+ /*
+ * Print the info field.
+ */
+ if (scsi_get_sense_info(sense, sense_len, SSD_DESC_INFO,
+ &val, NULL) == 0) {
+ sbuf_cat(sb, path_str);
+ scsi_info_sbuf(sb, cdb, cdb_len, inq_data, val);
+ sbuf_printf(sb, "\n");
}
/*
diff --git a/freebsd/sys/cam/scsi/scsi_all.h b/freebsd/sys/cam/scsi/scsi_all.h
index 80f8a221..735d0685 100644
--- a/freebsd/sys/cam/scsi/scsi_all.h
+++ b/freebsd/sys/cam/scsi/scsi_all.h
@@ -2931,6 +2931,7 @@ struct scsi_read_capacity_data_long
uint8_t length[4];
#define SRC16_PROT_EN 0x01
#define SRC16_P_TYPE 0x0e
+#define SRC16_P_TYPE_SHIFT 1
#define SRC16_PTYPE_1 0x00
#define SRC16_PTYPE_2 0x02
#define SRC16_PTYPE_3 0x04
@@ -3749,8 +3750,8 @@ void scsi_command_sbuf(struct sbuf *sb, uint8_t *cdb, int cdb_len,
void scsi_progress_sbuf(struct sbuf *sb, uint16_t progress);
int scsi_sks_sbuf(struct sbuf *sb, int sense_key, uint8_t *sks);
void scsi_fru_sbuf(struct sbuf *sb, uint64_t fru);
-void scsi_stream_sbuf(struct sbuf *sb, uint8_t stream_bits, uint64_t info);
-void scsi_block_sbuf(struct sbuf *sb, uint8_t block_bits, uint64_t info);
+void scsi_stream_sbuf(struct sbuf *sb, uint8_t stream_bits);
+void scsi_block_sbuf(struct sbuf *sb, uint8_t block_bits);
void scsi_sense_info_sbuf(struct sbuf *sb, struct scsi_sense_data *sense,
u_int sense_len, uint8_t *cdb, int cdb_len,
struct scsi_inquiry_data *inq_data,
diff --git a/freebsd/sys/dev/cadence/if_cgem.c b/freebsd/sys/dev/cadence/if_cgem.c
index 191362c4..34340f22 100644
--- a/freebsd/sys/dev/cadence/if_cgem.c
+++ b/freebsd/sys/dev/cadence/if_cgem.c
@@ -107,6 +107,14 @@ __FBSDID("$FreeBSD$");
#define CGEM_CKSUM_ASSIST (CSUM_IP | CSUM_TCP | CSUM_UDP | \
CSUM_TCP_IPV6 | CSUM_UDP_IPV6)
+#ifndef __rtems__
+static struct ofw_compat_data compat_data[] = {
+ { "cadence,gem", 1 },
+ { "cdns,macb", 1 },
+ { NULL, 0 },
+};
+#endif /* __rtems__ */
+
struct cgem_softc {
if_t ifp;
struct mtx sc_mtx;
@@ -1724,7 +1732,7 @@ cgem_probe(device_t dev)
if (!ofw_bus_status_okay(dev))
return (ENXIO);
- if (!ofw_bus_is_compatible(dev, "cadence,gem"))
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
return (ENXIO);
#endif /* __rtems__ */
diff --git a/freebsd/sys/dev/e1000/if_em.c b/freebsd/sys/dev/e1000/if_em.c
index 68e78ef0..1988cc07 100644
--- a/freebsd/sys/dev/e1000/if_em.c
+++ b/freebsd/sys/dev/e1000/if_em.c
@@ -1272,21 +1272,7 @@ em_if_init(if_ctx_t ctx)
/* Setup Multicast table */
em_if_multi_set(ctx);
- /*
- * Figure out the desired mbuf
- * pool for doing jumbos
- */
- if (adapter->hw.mac.max_frame_size <= 2048)
- adapter->rx_mbuf_sz = MCLBYTES;
-#ifndef CONTIGMALLOC_WORKS
- else
- adapter->rx_mbuf_sz = MJUMPAGESIZE;
-#else
- else if (adapter->hw.mac.max_frame_size <= 4096)
- adapter->rx_mbuf_sz = MJUMPAGESIZE;
- else
- adapter->rx_mbuf_sz = MJUM9BYTES;
-#endif
+ adapter->rx_mbuf_sz = iflib_get_rx_mbuf_sz(ctx);
em_initialize_receive_unit(ctx);
/* Use real VLAN Filter support? */
diff --git a/freebsd/sys/dev/fdt/fdt_common.c b/freebsd/sys/dev/fdt/fdt_common.c
index ff32dc0a..12979fda 100644
--- a/freebsd/sys/dev/fdt/fdt_common.c
+++ b/freebsd/sys/dev/fdt/fdt_common.c
@@ -401,6 +401,9 @@ fdt_get_phyaddr(phandle_t node, device_t dev, int *phy_addr, void **phy_sc)
*phy_addr = phy_reg;
+ if (phy_sc == NULL)
+ return (0);
+
/*
* Search for softc used to communicate with phy.
*/
diff --git a/freebsd/sys/dev/nvme/nvme.h b/freebsd/sys/dev/nvme/nvme.h
index 845ba75b..ae48a82f 100644
--- a/freebsd/sys/dev/nvme/nvme.h
+++ b/freebsd/sys/dev/nvme/nvme.h
@@ -349,6 +349,20 @@
#define NVME_NS_DATA_FPI_SUPP_SHIFT (7)
#define NVME_NS_DATA_FPI_SUPP_MASK (0x1)
+/** Deallocate Logical Block Features */
+/* deallocated logical block read behavior */
+#define NVME_NS_DATA_DLFEAT_READ_SHIFT (0)
+#define NVME_NS_DATA_DLFEAT_READ_MASK (0x07)
+#define NVME_NS_DATA_DLFEAT_READ_NR (0x00)
+#define NVME_NS_DATA_DLFEAT_READ_00 (0x01)
+#define NVME_NS_DATA_DLFEAT_READ_FF (0x02)
+/* supports the Deallocate bit in the Write Zeroes */
+#define NVME_NS_DATA_DLFEAT_DWZ_SHIFT (3)
+#define NVME_NS_DATA_DLFEAT_DWZ_MASK (0x01)
+/* Guard field for deallocated logical blocks is set to the CRC */
+#define NVME_NS_DATA_DLFEAT_GCRC_SHIFT (4)
+#define NVME_NS_DATA_DLFEAT_GCRC_MASK (0x01)
+
/** lba format support */
/* metadata size */
#define NVME_NS_DATA_LBAF_MS_SHIFT (0)
diff --git a/freebsd/sys/dev/pci/pci.c b/freebsd/sys/dev/pci/pci.c
index 09d1ee42..56c3f589 100644
--- a/freebsd/sys/dev/pci/pci.c
+++ b/freebsd/sys/dev/pci/pci.c
@@ -127,6 +127,10 @@ static int pci_remap_intr_method(device_t bus, device_t dev,
u_int irq);
static void pci_hint_device_unit(device_t acdev, device_t child,
const char *name, int *unitp);
+static int pci_reset_post(device_t dev, device_t child);
+static int pci_reset_prepare(device_t dev, device_t child);
+static int pci_reset_child(device_t dev, device_t child,
+ int flags);
static int pci_get_id_method(device_t dev, device_t child,
enum pci_id_type type, uintptr_t *rid);
@@ -151,6 +155,9 @@ static device_method_t pci_methods[] = {
DEVMETHOD(bus_driver_added, pci_driver_added),
DEVMETHOD(bus_setup_intr, pci_setup_intr),
DEVMETHOD(bus_teardown_intr, pci_teardown_intr),
+ DEVMETHOD(bus_reset_prepare, pci_reset_prepare),
+ DEVMETHOD(bus_reset_post, pci_reset_post),
+ DEVMETHOD(bus_reset_child, pci_reset_child),
DEVMETHOD(bus_get_dma_tag, pci_get_dma_tag),
DEVMETHOD(bus_get_resource_list,pci_get_resource_list),
@@ -6374,6 +6381,94 @@ pcie_flr(device_t dev, u_int max_delay, bool force)
return (true);
}
+/*
+ * Attempt a power-management reset by cycling the device in/out of D3
+ * state. PCI spec says we can only go into D3 state from D0 state.
+ * Transition from D[12] into D0 before going to D3 state.
+ */
+int
+pci_power_reset(device_t dev)
+{
+ int ps;
+
+ ps = pci_get_powerstate(dev);
+ if (ps != PCI_POWERSTATE_D0 && ps != PCI_POWERSTATE_D3)
+ pci_set_powerstate(dev, PCI_POWERSTATE_D0);
+ pci_set_powerstate(dev, PCI_POWERSTATE_D3);
+ pci_set_powerstate(dev, ps);
+ return (0);
+}
+
+/*
+ * Try link drop and retrain of the downstream port of upstream
+ * switch, for PCIe. According to the PCIe 3.0 spec 6.6.1, this must
+ * cause Conventional Hot reset of the device in the slot.
+ * Alternative, for PCIe, could be the secondary bus reset initiatied
+ * on the upstream switch PCIR_BRIDGECTL_1, bit 6.
+ */
+int
+pcie_link_reset(device_t port, int pcie_location)
+{
+ uint16_t v;
+
+ v = pci_read_config(port, pcie_location + PCIER_LINK_CTL, 2);
+ v |= PCIEM_LINK_CTL_LINK_DIS;
+ pci_write_config(port, pcie_location + PCIER_LINK_CTL, v, 2);
+ pause_sbt("pcier1", mstosbt(20), 0, 0);
+ v &= ~PCIEM_LINK_CTL_LINK_DIS;
+ v |= PCIEM_LINK_CTL_RETRAIN_LINK;
+ pci_write_config(port, pcie_location + PCIER_LINK_CTL, v, 2);
+ pause_sbt("pcier2", mstosbt(100), 0, 0); /* 100 ms */
+ v = pci_read_config(port, pcie_location + PCIER_LINK_STA, 2);
+ return ((v & PCIEM_LINK_STA_TRAINING) != 0 ? ETIMEDOUT : 0);
+}
+
+static int
+pci_reset_post(device_t dev, device_t child)
+{
+
+ if (dev == device_get_parent(child))
+ pci_restore_state(child);
+ return (0);
+}
+
+static int
+pci_reset_prepare(device_t dev, device_t child)
+{
+
+ if (dev == device_get_parent(child))
+ pci_save_state(child);
+ return (0);
+}
+
+static int
+pci_reset_child(device_t dev, device_t child, int flags)
+{
+ int error;
+
+ if (dev == NULL || device_get_parent(child) != dev)
+ return (0);
+ if ((flags & DEVF_RESET_DETACH) != 0) {
+ error = device_get_state(child) == DS_ATTACHED ?
+ device_detach(child) : 0;
+ } else {
+ error = BUS_SUSPEND_CHILD(dev, child);
+ }
+ if (error == 0) {
+ if (!pcie_flr(child, 1000, false)) {
+ error = BUS_RESET_PREPARE(dev, child);
+ if (error == 0)
+ pci_power_reset(child);
+ BUS_RESET_POST(dev, child);
+ }
+ if ((flags & DEVF_RESET_DETACH) != 0)
+ device_probe_and_attach(child);
+ else
+ BUS_RESUME_CHILD(dev, child);
+ }
+ return (error);
+}
+
const struct pci_device_table *
pci_match_device(device_t child, const struct pci_device_table *id, size_t nelt)
{
diff --git a/freebsd/sys/dev/pci/pci_pci.c b/freebsd/sys/dev/pci/pci_pci.c
index ec52e1fb..30fbbc09 100644
--- a/freebsd/sys/dev/pci/pci_pci.c
+++ b/freebsd/sys/dev/pci/pci_pci.c
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
+#include <sys/pciio.h>
#include <sys/rman.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
@@ -82,6 +83,7 @@ static void pcib_pcie_dll_timeout(void *arg);
#endif
static int pcib_request_feature_default(device_t pcib, device_t dev,
enum pci_feature feature);
+static int pcib_reset_child(device_t dev, device_t child, int flags);
static device_method_t pcib_methods[] = {
/* Device interface */
@@ -108,6 +110,7 @@ static device_method_t pcib_methods[] = {
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+ DEVMETHOD(bus_reset_child, pcib_reset_child),
/* pcib interface */
DEVMETHOD(pcib_maxslots, pcib_ari_maxslots),
@@ -2910,3 +2913,31 @@ pcib_request_feature_default(device_t pcib, device_t dev,
bus = device_get_parent(pcib);
return (PCIB_REQUEST_FEATURE(device_get_parent(bus), dev, feature));
}
+
+static int
+pcib_reset_child(device_t dev, device_t child, int flags)
+{
+ struct pci_devinfo *pdinfo;
+ int error;
+
+ error = 0;
+ if (dev == NULL || device_get_parent(child) != dev)
+ goto out;
+ error = ENXIO;
+ if (device_get_devclass(child) != devclass_find("pci"))
+ goto out;
+ pdinfo = device_get_ivars(dev);
+ if (pdinfo->cfg.pcie.pcie_location != 0 &&
+ (pdinfo->cfg.pcie.pcie_type == PCIEM_TYPE_DOWNSTREAM_PORT ||
+ pdinfo->cfg.pcie.pcie_type == PCIEM_TYPE_ROOT_PORT)) {
+ error = bus_helper_reset_prepare(child, flags);
+ if (error == 0) {
+ error = pcie_link_reset(dev,
+ pdinfo->cfg.pcie.pcie_location);
+ /* XXXKIB call _post even if error != 0 ? */
+ bus_helper_reset_post(child, flags);
+ }
+ }
+out:
+ return (error);
+}
diff --git a/freebsd/sys/dev/pci/pcivar.h b/freebsd/sys/dev/pci/pcivar.h
index 8fd0d9f7..b530fdcb 100644
--- a/freebsd/sys/dev/pci/pcivar.h
+++ b/freebsd/sys/dev/pci/pcivar.h
@@ -674,6 +674,7 @@ int pci_get_max_read_req(device_t dev);
void pci_restore_state(device_t dev);
void pci_save_state(device_t dev);
int pci_set_max_read_req(device_t dev, int size);
+int pci_power_reset(device_t dev);
uint32_t pcie_read_config(device_t dev, int reg, int width);
void pcie_write_config(device_t dev, int reg, uint32_t value, int width);
uint32_t pcie_adjust_config(device_t dev, int reg, uint32_t mask,
@@ -681,6 +682,7 @@ uint32_t pcie_adjust_config(device_t dev, int reg, uint32_t mask,
bool pcie_flr(device_t dev, u_int max_delay, bool force);
int pcie_get_max_completion_timeout(device_t dev);
bool pcie_wait_for_pending_transactions(device_t dev, u_int max_delay);
+int pcie_link_reset(device_t port, int pcie_location);
void pci_print_faulted_dev(void);
diff --git a/freebsd/sys/dev/rtwn/if_rtwn.c b/freebsd/sys/dev/rtwn/if_rtwn.c
index f660ea5d..0ca83e8a 100644
--- a/freebsd/sys/dev/rtwn/if_rtwn.c
+++ b/freebsd/sys/dev/rtwn/if_rtwn.c
@@ -1562,10 +1562,6 @@ rtwn_set_channel(struct ieee80211com *ic)
RTWN_LOCK(sc);
rtwn_set_chan(sc, c);
- sc->sc_rxtap.wr_chan_freq = htole16(c->ic_freq);
- sc->sc_rxtap.wr_chan_flags = htole16(c->ic_flags);
- sc->sc_txtap.wt_chan_freq = htole16(c->ic_freq);
- sc->sc_txtap.wt_chan_flags = htole16(c->ic_flags);
RTWN_UNLOCK(sc);
}
diff --git a/freebsd/sys/dev/rtwn/if_rtwnvar.h b/freebsd/sys/dev/rtwn/if_rtwnvar.h
index 3ebcba52..a6e7ea9f 100644
--- a/freebsd/sys/dev/rtwn/if_rtwnvar.h
+++ b/freebsd/sys/dev/rtwn/if_rtwnvar.h
@@ -62,9 +62,10 @@ struct rtwn_rx_radiotap_header {
struct rtwn_tx_radiotap_header {
struct ieee80211_radiotap_header wt_ihdr;
uint8_t wt_flags;
+ uint8_t wt_pad;
uint16_t wt_chan_freq;
uint16_t wt_chan_flags;
-} __packed __aligned(8);
+} __packed;
#define RTWN_TX_RADIOTAP_PRESENT \
(1 << IEEE80211_RADIOTAP_FLAGS | \
diff --git a/freebsd/sys/dev/sdhci/sdhci.c b/freebsd/sys/dev/sdhci/sdhci.c
index b9a8a38d..952fbd50 100644
--- a/freebsd/sys/dev/sdhci/sdhci.c
+++ b/freebsd/sys/dev/sdhci/sdhci.c
@@ -1564,23 +1564,23 @@ sdhci_retune(void *arg)
static void
sdhci_req_done(struct sdhci_slot *slot)
{
- union ccb *ccb;
+ union ccb *ccb;
if (__predict_false(sdhci_debug > 1))
slot_printf(slot, "%s\n", __func__);
if (slot->ccb != NULL && slot->curcmd != NULL) {
callout_stop(&slot->timeout_callout);
- ccb = slot->ccb;
- slot->ccb = NULL;
+ ccb = slot->ccb;
+ slot->ccb = NULL;
slot->curcmd = NULL;
- /* Tell CAM the request is finished */
- struct ccb_mmcio *mmcio;
- mmcio = &ccb->mmcio;
+ /* Tell CAM the request is finished */
+ struct ccb_mmcio *mmcio;
+ mmcio = &ccb->mmcio;
- ccb->ccb_h.status =
- (mmcio->cmd.error == 0 ? CAM_REQ_CMP : CAM_REQ_CMP_ERR);
- xpt_done(ccb);
+ ccb->ccb_h.status =
+ (mmcio->cmd.error == 0 ? CAM_REQ_CMP : CAM_REQ_CMP_ERR);
+ xpt_done(ccb);
}
}
#else
@@ -2498,47 +2498,45 @@ void
sdhci_start_slot(struct sdhci_slot *slot)
{
- if ((slot->devq = cam_simq_alloc(1)) == NULL) {
- goto fail;
- }
-
- mtx_init(&slot->sim_mtx, "sdhcisim", NULL, MTX_DEF);
- slot->sim = cam_sim_alloc(sdhci_cam_action, sdhci_cam_poll,
- "sdhci_slot", slot, device_get_unit(slot->bus),
- &slot->sim_mtx, 1, 1, slot->devq);
-
- if (slot->sim == NULL) {
- cam_simq_free(slot->devq);
- slot_printf(slot, "cannot allocate CAM SIM\n");
- goto fail;
- }
-
- mtx_lock(&slot->sim_mtx);
- if (xpt_bus_register(slot->sim, slot->bus, 0) != 0) {
- slot_printf(slot,
- "cannot register SCSI pass-through bus\n");
- cam_sim_free(slot->sim, FALSE);
- cam_simq_free(slot->devq);
- mtx_unlock(&slot->sim_mtx);
- goto fail;
- }
-
- mtx_unlock(&slot->sim_mtx);
- /* End CAM-specific init */
+ if ((slot->devq = cam_simq_alloc(1)) == NULL)
+ goto fail;
+
+ mtx_init(&slot->sim_mtx, "sdhcisim", NULL, MTX_DEF);
+ slot->sim = cam_sim_alloc(sdhci_cam_action, sdhci_cam_poll,
+ "sdhci_slot", slot, device_get_unit(slot->bus),
+ &slot->sim_mtx, 1, 1, slot->devq);
+
+ if (slot->sim == NULL) {
+ cam_simq_free(slot->devq);
+ slot_printf(slot, "cannot allocate CAM SIM\n");
+ goto fail;
+ }
+
+ mtx_lock(&slot->sim_mtx);
+ if (xpt_bus_register(slot->sim, slot->bus, 0) != 0) {
+ slot_printf(slot, "cannot register SCSI pass-through bus\n");
+ cam_sim_free(slot->sim, FALSE);
+ cam_simq_free(slot->devq);
+ mtx_unlock(&slot->sim_mtx);
+ goto fail;
+ }
+ mtx_unlock(&slot->sim_mtx);
+
+ /* End CAM-specific init */
slot->card_present = 0;
sdhci_card_task(slot, 0);
- return;
+ return;
fail:
- if (slot->sim != NULL) {
- mtx_lock(&slot->sim_mtx);
- xpt_bus_deregister(cam_sim_path(slot->sim));
- cam_sim_free(slot->sim, FALSE);
- mtx_unlock(&slot->sim_mtx);
- }
-
- if (slot->devq != NULL)
- cam_simq_free(slot->devq);
+ if (slot->sim != NULL) {
+ mtx_lock(&slot->sim_mtx);
+ xpt_bus_deregister(cam_sim_path(slot->sim));
+ cam_sim_free(slot->sim, FALSE);
+ mtx_unlock(&slot->sim_mtx);
+ }
+
+ if (slot->devq != NULL)
+ cam_simq_free(slot->devq);
}
static void
@@ -2668,15 +2666,13 @@ sdhci_cam_get_possible_host_clock(const struct sdhci_slot *slot,
clock = max_clock;
if (slot->version < SDHCI_SPEC_300) {
- for (i = 0; i < SDHCI_200_MAX_DIVIDER;
- i <<= 1) {
+ for (i = 0; i < SDHCI_200_MAX_DIVIDER; i <<= 1) {
if (clock <= proposed_clock)
break;
clock >>= 1;
}
} else {
- for (i = 0; i < SDHCI_300_MAX_DIVIDER;
- i += 2) {
+ for (i = 0; i < SDHCI_300_MAX_DIVIDER; i += 2) {
if (clock <= proposed_clock)
break;
clock = max_clock / (i + 2);
@@ -2726,7 +2722,7 @@ sdhci_cam_settran_settings(struct sdhci_slot *slot, union ccb *ccb)
slot_printf(slot, "Bus mode => %d\n", ios->bus_mode);
}
- /* XXX Provide a way to call a chip-specific IOS update, required for TI */
+ /* XXX Provide a way to call a chip-specific IOS update, required for TI */
return (sdhci_cam_update_ios(slot));
}
@@ -2794,7 +2790,7 @@ sdhci_cam_request(struct sdhci_slot *slot, union ccb *ccb)
if (mmcio->cmd.data != NULL) {
if (mmcio->cmd.data->len == 0 || mmcio->cmd.data->flags == 0)
panic("data->len = %d, data->flags = %d -- something is b0rked",
- (int)mmcio->cmd.data->len, mmcio->cmd.data->flags);
+ (int)mmcio->cmd.data->len, mmcio->cmd.data->flags);
}
slot->ccb = ccb;
slot->flags = 0;
diff --git a/freebsd/sys/dev/sdhci/sdhci.h b/freebsd/sys/dev/sdhci/sdhci.h
index 4c4c2745..38c5e1b9 100644
--- a/freebsd/sys/dev/sdhci/sdhci.h
+++ b/freebsd/sys/dev/sdhci/sdhci.h
@@ -413,10 +413,10 @@ struct sdhci_slot {
#ifdef MMCCAM
/* CAM stuff */
union ccb *ccb;
- struct cam_devq *devq;
- struct cam_sim *sim;
- struct mtx sim_mtx;
- u_char card_present; /* XXX Maybe derive this from elsewhere? */
+ struct cam_devq *devq;
+ struct cam_sim *sim;
+ struct mtx sim_mtx;
+ u_char card_present; /* XXX Maybe derive this from elsewhere? */
#endif
};
diff --git a/freebsd/sys/dev/usb/net/if_smsc.c b/freebsd/sys/dev/usb/net/if_smsc.c
index 87e181d8..74516536 100644
--- a/freebsd/sys/dev/usb/net/if_smsc.c
+++ b/freebsd/sys/dev/usb/net/if_smsc.c
@@ -99,6 +99,7 @@ __FBSDID("$FreeBSD$");
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/usb/usb_fdt_support.h>
#endif
#include <dev/usb/usb.h>
@@ -1561,147 +1562,6 @@ smsc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
return (rc);
}
-#ifdef FDT
-/*
- * This is FreeBSD-specific compatibility strings for RPi/RPi2
- */
-static phandle_t
-smsc_fdt_find_eth_node(phandle_t start)
-{
- phandle_t child, node;
-
- /* Traverse through entire tree to find usb ethernet nodes. */
- for (node = OF_child(start); node != 0; node = OF_peer(node)) {
- if ((ofw_bus_node_is_compatible(node, "net,ethernet") &&
- ofw_bus_node_is_compatible(node, "usb,device")) ||
- ofw_bus_node_is_compatible(node, "usb424,ec00"))
- return (node);
- child = smsc_fdt_find_eth_node(node);
- if (child != -1)
- return (child);
- }
-
- return (-1);
-}
-
-/*
- * Check if node's path is <*>/usb/hub/ethernet
- */
-static int
-smsc_fdt_is_usb_eth(phandle_t node)
-{
- char name[16];
- int len;
-
- memset(name, 0, sizeof(name));
- len = OF_getprop(node, "name", name, sizeof(name));
- if (len <= 0)
- return (0);
-
- if (strcmp(name, "ethernet"))
- return (0);
-
- node = OF_parent(node);
- if (node == -1)
- return (0);
- len = OF_getprop(node, "name", name, sizeof(name));
- if (len <= 0)
- return (0);
-
- if (strcmp(name, "hub"))
- return (0);
-
- node = OF_parent(node);
- if (node == -1)
- return (0);
- len = OF_getprop(node, "name", name, sizeof(name));
- if (len <= 0)
- return (0);
-
- if (strcmp(name, "usb"))
- return (0);
-
- return (1);
-}
-
-static phandle_t
-smsc_fdt_find_eth_node_by_path(phandle_t start)
-{
- phandle_t child, node;
-
- /* Traverse through entire tree to find usb ethernet nodes. */
- for (node = OF_child(start); node != 0; node = OF_peer(node)) {
- if (smsc_fdt_is_usb_eth(node))
- return (node);
- child = smsc_fdt_find_eth_node_by_path(node);
- if (child != -1)
- return (child);
- }
-
- return (-1);
-}
-
-/*
- * Look through known names that can contain mac address
- * return 0 if valid MAC address has been found
- */
-static int
-smsc_fdt_read_mac_property(phandle_t node, unsigned char *mac)
-{
- int len;
-
- /* Check if there is property */
- if ((len = OF_getproplen(node, "local-mac-address")) > 0) {
- if (len != ETHER_ADDR_LEN)
- return (EINVAL);
-
- OF_getprop(node, "local-mac-address", mac,
- ETHER_ADDR_LEN);
- return (0);
- }
-
- if ((len = OF_getproplen(node, "mac-address")) > 0) {
- if (len != ETHER_ADDR_LEN)
- return (EINVAL);
-
- OF_getprop(node, "mac-address", mac,
- ETHER_ADDR_LEN);
- return (0);
- }
-
- return (ENXIO);
-}
-
-/**
- * Get MAC address from FDT blob. Firmware or loader should fill
- * mac-address or local-mac-address property. Returns 0 if MAC address
- * obtained, error code otherwise.
- */
-static int
-smsc_fdt_find_mac(unsigned char *mac)
-{
- phandle_t node, root;
-
- root = OF_finddevice("/");
- node = smsc_fdt_find_eth_node(root);
- if (node != -1) {
- if (smsc_fdt_read_mac_property(node, mac) == 0)
- return (0);
- }
-
- /*
- * If it's not FreeBSD FDT blob for RPi, try more
- * generic .../usb/hub/ethernet
- */
- node = smsc_fdt_find_eth_node_by_path(root);
-
- if (node != -1)
- return smsc_fdt_read_mac_property(node, mac);
-
- return (ENXIO);
-}
-#endif
-
/**
* smsc_attach_post - Called after the driver attached to the USB interface
* @ue: the USB ethernet device
@@ -1750,7 +1610,7 @@ smsc_attach_post(struct usb_ether *ue)
err = smsc_eeprom_read(sc, 0x01, sc->sc_ue.ue_eaddr, ETHER_ADDR_LEN);
#ifdef FDT
if ((err != 0) || (!ETHER_IS_VALID(sc->sc_ue.ue_eaddr)))
- err = smsc_fdt_find_mac(sc->sc_ue.ue_eaddr);
+ err = usb_fdt_get_mac_addr(sc->sc_ue.ue_dev, &sc->sc_ue);
#endif
if ((err != 0) || (!ETHER_IS_VALID(sc->sc_ue.ue_eaddr))) {
read_random(sc->sc_ue.ue_eaddr, ETHER_ADDR_LEN);
diff --git a/freebsd/sys/dev/usb/net/if_urereg.h b/freebsd/sys/dev/usb/net/if_urereg.h
index 8eff1c25..cc70093f 100644
--- a/freebsd/sys/dev/usb/net/if_urereg.h
+++ b/freebsd/sys/dev/usb/net/if_urereg.h
@@ -176,7 +176,7 @@
#define URE_EEEP_CR_EEEP_TX 0x0002
/* PLA_WDT6_CTRL */
-#define URE_WDT6_SET_MODE 0x001
+#define URE_WDT6_SET_MODE 0x0010
/* PLA_TCR0 */
#define URE_TCR0_TX_EMPTY 0x0800
diff --git a/freebsd/sys/dev/usb/wlan/if_rsu.c b/freebsd/sys/dev/usb/wlan/if_rsu.c
index 45cd30ad..112b8675 100644
--- a/freebsd/sys/dev/usb/wlan/if_rsu.c
+++ b/freebsd/sys/dev/usb/wlan/if_rsu.c
@@ -2452,8 +2452,6 @@ rsu_rx_frame(struct rsu_softc *sc, struct mbuf *m)
tap->wr_rate = rxs.c_rate;
tap->wr_dbm_antsignal = rssi;
- tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq);
- tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags);
};
(void) ieee80211_add_rx_params(m, &rxs);
@@ -2755,7 +2753,6 @@ rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni,
struct mbuf *m0, struct rsu_data *data)
{
const struct ieee80211_txparam *tp = ni->ni_txparms;
- struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211_frame *wh;
struct ieee80211_key *k = NULL;
@@ -2899,8 +2896,6 @@ rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni,
struct rsu_tx_radiotap_header *tap = &sc->sc_txtap;
tap->wt_flags = 0;
- tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq);
- tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags);
ieee80211_radiotap_tx(vap, m0);
}
diff --git a/freebsd/sys/dev/usb/wlan/if_rsureg.h b/freebsd/sys/dev/usb/wlan/if_rsureg.h
index a6ab170b..246b06b7 100644
--- a/freebsd/sys/dev/usb/wlan/if_rsureg.h
+++ b/freebsd/sys/dev/usb/wlan/if_rsureg.h
@@ -800,9 +800,10 @@ struct rsu_rx_radiotap_header {
struct rsu_tx_radiotap_header {
struct ieee80211_radiotap_header wt_ihdr;
uint8_t wt_flags;
+ uint8_t wt_pad;
uint16_t wt_chan_freq;
uint16_t wt_chan_flags;
-} __packed __aligned(8);
+} __packed;
#define RSU_TX_RADIOTAP_PRESENT \
(1 << IEEE80211_RADIOTAP_FLAGS | \
diff --git a/freebsd/sys/dev/usb/wlan/if_rumvar.h b/freebsd/sys/dev/usb/wlan/if_rumvar.h
index 4ff831f4..e19a7088 100644
--- a/freebsd/sys/dev/usb/wlan/if_rumvar.h
+++ b/freebsd/sys/dev/usb/wlan/if_rumvar.h
@@ -49,7 +49,7 @@ struct rum_tx_radiotap_header {
uint16_t wt_chan_freq;
uint16_t wt_chan_flags;
uint8_t wt_antenna;
-} __packed __aligned(8);
+} __packed;
#define RT2573_TX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_FLAGS) | \
diff --git a/freebsd/sys/dev/usb/wlan/if_run.c b/freebsd/sys/dev/usb/wlan/if_run.c
index 5cec460e..2208e4fd 100644
--- a/freebsd/sys/dev/usb/wlan/if_run.c
+++ b/freebsd/sys/dev/usb/wlan/if_run.c
@@ -466,6 +466,7 @@ static void run_usb_timeout_cb(void *);
static void run_reset_livelock(struct run_softc *);
static void run_enable_tsf_sync(struct run_softc *);
static void run_enable_tsf(struct run_softc *);
+static void run_disable_tsf(struct run_softc *);
static void run_get_tsf(struct run_softc *, uint64_t *);
static void run_enable_mrr(struct run_softc *);
static void run_set_txpreamble(struct run_softc *);
@@ -2092,7 +2093,6 @@ run_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
struct run_vap *rvp = RUN_VAP(vap);
enum ieee80211_state ostate;
uint32_t sta[3];
- uint32_t tmp;
uint8_t ratectl;
uint8_t restart_ratectl = 0;
uint8_t bid = 1 << rvp->rvp_id;
@@ -2125,12 +2125,8 @@ run_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
sc->runbmap &= ~bid;
/* abort TSF synchronization if there is no vap running */
- if (--sc->running == 0) {
- run_read(sc, RT2860_BCN_TIME_CFG, &tmp);
- run_write(sc, RT2860_BCN_TIME_CFG,
- tmp & ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN |
- RT2860_TBTT_TIMER_EN));
- }
+ if (--sc->running == 0)
+ run_disable_tsf(sc);
break;
case IEEE80211_S_RUN:
@@ -2857,10 +2853,6 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen)
}
if (flags & RT2860_RX_L2PAD) {
- /*
- * XXX OpenBSD removes padding between header
- * and payload here...
- */
RUN_DPRINTF(sc, RUN_DEBUG_RECV,
"received RT2860_RX_L2PAD frame\n");
len += 2;
@@ -2871,8 +2863,8 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen)
wh = mtod(m, struct ieee80211_frame *);
- /* XXX wrong for monitor mode */
- if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
+ if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED) != 0 &&
+ (flags & RT2860_RX_DEC) != 0) {
wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;
m->m_flags |= M_WEP;
}
@@ -2902,8 +2894,8 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen)
uint16_t phy;
tap->wr_flags = 0;
- tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq);
- tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags);
+ if (flags & RT2860_RX_L2PAD)
+ tap->wr_flags |= IEEE80211_RADIOTAP_F_DATAPAD;
tap->wr_antsignal = rssi;
tap->wr_antenna = ant;
tap->wr_dbm_antsignal = run_rssi2dbm(sc, rssi, ant);
@@ -3170,16 +3162,23 @@ tr_setup:
vap = data->ni->ni_vap;
if (ieee80211_radiotap_active_vap(vap)) {
+ const struct ieee80211_frame *wh;
struct run_tx_radiotap_header *tap = &sc->sc_txtap;
struct rt2860_txwi *txwi =
(struct rt2860_txwi *)(&data->desc + sizeof(struct rt2870_txd));
+ int has_l2pad;
+
+ wh = mtod(m, struct ieee80211_frame *);
+ has_l2pad = IEEE80211_HAS_ADDR4(wh) !=
+ IEEE80211_QOS_HAS_SEQ(wh);
+
tap->wt_flags = 0;
tap->wt_rate = rt2860_rates[data->ridx].rate;
- tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq);
- tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags);
tap->wt_hwqueue = index;
if (le16toh(txwi->phy) & RT2860_PHY_SHPRE)
tap->wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
+ if (has_l2pad)
+ tap->wt_flags |= IEEE80211_RADIOTAP_F_DATAPAD;
ieee80211_radiotap_tx(vap, m);
}
@@ -4869,15 +4868,11 @@ static void
run_scan_start(struct ieee80211com *ic)
{
struct run_softc *sc = ic->ic_softc;
- uint32_t tmp;
RUN_LOCK(sc);
/* abort TSF synchronization */
- run_read(sc, RT2860_BCN_TIME_CFG, &tmp);
- run_write(sc, RT2860_BCN_TIME_CFG,
- tmp & ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN |
- RT2860_TBTT_TIMER_EN));
+ run_disable_tsf(sc);
run_set_bssid(sc, ieee80211broadcastaddr);
RUN_UNLOCK(sc);
@@ -5164,6 +5159,18 @@ run_enable_tsf(struct run_softc *sc)
}
static void
+run_disable_tsf(struct run_softc *sc)
+{
+ uint32_t tmp;
+
+ if (run_read(sc, RT2860_BCN_TIME_CFG, &tmp) == 0) {
+ tmp &= ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN |
+ RT2860_TBTT_TIMER_EN);
+ run_write(sc, RT2860_BCN_TIME_CFG, tmp);
+ }
+}
+
+static void
run_get_tsf(struct run_softc *sc, uint64_t *buf)
{
run_read_region_1(sc, RT2860_TSF_TIMER_DW0, (uint8_t *)buf,
@@ -6114,10 +6121,7 @@ run_init_locked(struct run_softc *sc)
}
/* abort TSF synchronization */
- run_read(sc, RT2860_BCN_TIME_CFG, &tmp);
- tmp &= ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN |
- RT2860_TBTT_TIMER_EN);
- run_write(sc, RT2860_BCN_TIME_CFG, tmp);
+ run_disable_tsf(sc);
/* clear RX WCID search table */
run_set_region_4(sc, RT2860_WCID_ENTRY(0), 0, 512);
diff --git a/freebsd/sys/dev/usb/wlan/if_runvar.h b/freebsd/sys/dev/usb/wlan/if_runvar.h
index 7209bfc7..a17d5b46 100644
--- a/freebsd/sys/dev/usb/wlan/if_runvar.h
+++ b/freebsd/sys/dev/usb/wlan/if_runvar.h
@@ -71,7 +71,7 @@ struct run_tx_radiotap_header {
uint16_t wt_chan_freq;
uint16_t wt_chan_flags;
uint8_t wt_hwqueue;
-} __packed __aligned(8);
+} __packed;
#define IEEE80211_RADIOTAP_HWQUEUE 15
diff --git a/freebsd/sys/dev/usb/wlan/if_uath.c b/freebsd/sys/dev/usb/wlan/if_uath.c
index 541263ab..9f0c9d5d 100644
--- a/freebsd/sys/dev/usb/wlan/if_uath.c
+++ b/freebsd/sys/dev/usb/wlan/if_uath.c
@@ -1278,8 +1278,8 @@ uath_watchdog(void *arg)
if (sc->sc_tx_timer > 0) {
if (--sc->sc_tx_timer == 0) {
device_printf(sc->sc_dev, "device timeout\n");
- /*uath_init(sc); XXX needs a process context! */
counter_u64_add(ic->ic_oerrors, 1);
+ ieee80211_restart_all(ic);
return;
}
callout_reset(&sc->watchdog_ch, hz, uath_watchdog, sc);
diff --git a/freebsd/sys/dev/usb/wlan/if_uathvar.h b/freebsd/sys/dev/usb/wlan/if_uathvar.h
index a38f54fc..a0ef4eab 100644
--- a/freebsd/sys/dev/usb/wlan/if_uathvar.h
+++ b/freebsd/sys/dev/usb/wlan/if_uathvar.h
@@ -67,9 +67,10 @@ struct uath_rx_radiotap_header {
struct uath_tx_radiotap_header {
struct ieee80211_radiotap_header wt_ihdr;
uint8_t wt_flags;
+ uint8_t wt_pad;
uint16_t wt_chan_freq;
uint16_t wt_chan_flags;
-} __packed __aligned(8);
+} __packed;
#define UATH_TX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_FLAGS) | \
diff --git a/freebsd/sys/dev/usb/wlan/if_upgtvar.h b/freebsd/sys/dev/usb/wlan/if_upgtvar.h
index ce996f6a..9d4c85e6 100644
--- a/freebsd/sys/dev/usb/wlan/if_upgtvar.h
+++ b/freebsd/sys/dev/usb/wlan/if_upgtvar.h
@@ -394,7 +394,7 @@ struct upgt_tx_radiotap_header {
uint8_t wt_rate;
uint16_t wt_chan_freq;
uint16_t wt_chan_flags;
-} __packed __aligned(8);
+} __packed;
#define UPGT_TX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_FLAGS) | \
diff --git a/freebsd/sys/dev/usb/wlan/if_uralvar.h b/freebsd/sys/dev/usb/wlan/if_uralvar.h
index dd863fe0..b59b7911 100644
--- a/freebsd/sys/dev/usb/wlan/if_uralvar.h
+++ b/freebsd/sys/dev/usb/wlan/if_uralvar.h
@@ -51,7 +51,7 @@ struct ural_tx_radiotap_header {
uint16_t wt_chan_freq;
uint16_t wt_chan_flags;
uint8_t wt_antenna;
-} __packed __aligned(8);
+} __packed;
#define RAL_TX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_FLAGS) | \
diff --git a/freebsd/sys/dev/usb/wlan/if_urtw.c b/freebsd/sys/dev/usb/wlan/if_urtw.c
index 84f28d56..aba334af 100644
--- a/freebsd/sys/dev/usb/wlan/if_urtw.c
+++ b/freebsd/sys/dev/usb/wlan/if_urtw.c
@@ -754,6 +754,7 @@ static void urtw_free_tx_data_list(struct urtw_softc *);
static void urtw_free_rx_data_list(struct urtw_softc *);
static void urtw_free_data_list(struct urtw_softc *,
struct urtw_data data[], int, int);
+static usb_error_t urtw_set_macaddr(struct urtw_softc *, const uint8_t *);
static usb_error_t urtw_adapter_start(struct urtw_softc *);
static usb_error_t urtw_adapter_start_b(struct urtw_softc *);
static usb_error_t urtw_set_mode(struct urtw_softc *, uint32_t);
@@ -1189,9 +1190,23 @@ fail:
}
static usb_error_t
+urtw_set_macaddr(struct urtw_softc *sc, const uint8_t *macaddr)
+{
+ usb_error_t error;
+
+ urtw_write32_m(sc, URTW_MAC0, ((const uint32_t *)macaddr)[0]);
+ urtw_write16_m(sc, URTW_MAC4, ((const uint32_t *)macaddr)[1] & 0xffff);
+
+fail:
+ return (error);
+}
+
+static usb_error_t
urtw_adapter_start(struct urtw_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+ const uint8_t *macaddr;
usb_error_t error;
error = urtw_reset(sc);
@@ -1211,8 +1226,11 @@ urtw_adapter_start(struct urtw_softc *sc)
if (error)
goto fail;
/* applying MAC address again. */
- urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)ic->ic_macaddr)[0]);
- urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)ic->ic_macaddr)[1] & 0xffff);
+ macaddr = vap ? vap->iv_myaddr : ic->ic_macaddr;
+ urtw_set_macaddr(sc, macaddr);
+ if (error)
+ goto fail;
+
error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
if (error)
goto fail;
@@ -1699,11 +1717,7 @@ urtw_tx_start(struct urtw_softc *sc, struct ieee80211_node *ni, struct mbuf *m0,
if (ieee80211_radiotap_active_vap(vap)) {
struct urtw_tx_radiotap_header *tap = &sc->sc_txtap;
- /* XXX Are variables correct? */
tap->wt_flags = 0;
- tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq);
- tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags);
-
ieee80211_radiotap_tx(vap, m0);
}
@@ -1897,11 +1911,13 @@ static void
urtw_watchdog(void *arg)
{
struct urtw_softc *sc = arg;
+ struct ieee80211com *ic = &sc->sc_ic;
if (sc->sc_txtimer > 0) {
if (--sc->sc_txtimer == 0) {
device_printf(sc->sc_dev, "device timeout\n");
- counter_u64_add(sc->sc_ic.ic_oerrors, 1);
+ counter_u64_add(ic->ic_oerrors, 1);
+ ieee80211_restart_all(ic);
return;
}
callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc);
@@ -3184,6 +3200,8 @@ static usb_error_t
urtw_8225v2b_rf_init(struct urtw_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+ const uint8_t *macaddr;
unsigned int i;
uint8_t data8;
usb_error_t error;
@@ -3231,8 +3249,10 @@ urtw_8225v2b_rf_init(struct urtw_softc *sc)
urtw_write8_m(sc, URTW_CONFIG1, data8);
/* applying MAC address again. */
- urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)ic->ic_macaddr)[0]);
- urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)ic->ic_macaddr)[1] & 0xffff);
+ macaddr = vap ? vap->iv_myaddr : ic->ic_macaddr;
+ error = urtw_set_macaddr(sc, macaddr);
+ if (error)
+ goto fail;
error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
if (error)
@@ -3938,6 +3958,7 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
struct urtw_softc *sc = data->sc;
struct ieee80211com *ic = &sc->sc_ic;
uint8_t noise = 0, rate;
+ uint64_t mactime;
usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
@@ -3957,6 +3978,9 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
/* XXX correct? */
rssi = rx->rssi & URTW_RX_RSSI_MASK;
noise = rx->noise;
+
+ if (ieee80211_radiotap_active(ic))
+ mactime = rx->mactime;
} else {
struct urtw_8187l_rxhdr *rx;
@@ -3973,6 +3997,9 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
/* XXX correct? */
rssi = rx->rssi & URTW_RX_8187L_RSSI_MASK;
noise = rx->noise;
+
+ if (ieee80211_radiotap_active(ic))
+ mactime = rx->mactime;
}
if (flen < IEEE80211_ACK_LEN)
@@ -3992,9 +4019,8 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
if (ieee80211_radiotap_active(ic)) {
struct urtw_rx_radiotap_header *tap = &sc->sc_rxtap;
- /* XXX Are variables correct? */
- tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq);
- tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags);
+ tap->wr_tsf = mactime;
+ tap->wr_flags = 0;
tap->wr_dbm_antsignal = (int8_t)rssi;
}
diff --git a/freebsd/sys/dev/usb/wlan/if_urtwvar.h b/freebsd/sys/dev/usb/wlan/if_urtwvar.h
index 1b5e2cd1..87c24d64 100644
--- a/freebsd/sys/dev/usb/wlan/if_urtwvar.h
+++ b/freebsd/sys/dev/usb/wlan/if_urtwvar.h
@@ -55,23 +55,27 @@ typedef STAILQ_HEAD(, urtw_data) urtw_datahead;
struct urtw_rx_radiotap_header {
struct ieee80211_radiotap_header wr_ihdr;
+ uint64_t wr_tsf;
uint8_t wr_flags;
+ uint8_t wr_pad;
uint16_t wr_chan_freq;
uint16_t wr_chan_flags;
int8_t wr_dbm_antsignal;
} __packed __aligned(8);
#define URTW_RX_RADIOTAP_PRESENT \
- ((1 << IEEE80211_RADIOTAP_FLAGS) | \
+ ((1 << IEEE80211_RADIOTAP_TSFT) | \
+ (1 << IEEE80211_RADIOTAP_FLAGS) | \
(1 << IEEE80211_RADIOTAP_CHANNEL) | \
(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL))
struct urtw_tx_radiotap_header {
struct ieee80211_radiotap_header wt_ihdr;
uint8_t wt_flags;
+ uint8_t wt_pad;
uint16_t wt_chan_freq;
uint16_t wt_chan_flags;
-} __packed __aligned(8);
+} __packed;
#define URTW_TX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_FLAGS) | \
diff --git a/freebsd/sys/dev/usb/wlan/if_zydreg.h b/freebsd/sys/dev/usb/wlan/if_zydreg.h
index 8c4a16c5..a4523199 100644
--- a/freebsd/sys/dev/usb/wlan/if_zydreg.h
+++ b/freebsd/sys/dev/usb/wlan/if_zydreg.h
@@ -1200,7 +1200,7 @@ struct zyd_tx_radiotap_header {
uint8_t wt_rate;
uint16_t wt_chan_freq;
uint16_t wt_chan_flags;
-} __packed __aligned(8);
+} __packed;
#define ZYD_TX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_FLAGS) | \
diff --git a/freebsd/sys/kern/init_main.c b/freebsd/sys/kern/init_main.c
index 43eaea5c..224c9f66 100644
--- a/freebsd/sys/kern/init_main.c
+++ b/freebsd/sys/kern/init_main.c
@@ -439,7 +439,6 @@ struct sysentvec null_sysvec = {
.sv_coredump = NULL,
.sv_imgact_try = NULL,
.sv_minsigstksz = 0,
- .sv_pagesize = PAGE_SIZE,
.sv_minuser = VM_MIN_ADDRESS,
.sv_maxuser = VM_MAXUSER_ADDRESS,
.sv_usrstack = USRSTACK,
diff --git a/freebsd/sys/kern/kern_intr.c b/freebsd/sys/kern/kern_intr.c
index 2ba76e88..8a85a5b2 100644
--- a/freebsd/sys/kern/kern_intr.c
+++ b/freebsd/sys/kern/kern_intr.c
@@ -231,10 +231,20 @@ intr_event_update(struct intr_event *ie)
}
/*
- * If the handler names were too long, add +'s to indicate missing
- * names. If we run out of room and still have +'s to add, change
- * the last character from a + to a *.
+ * If there is only one handler and its name is too long, just copy in
+ * as much of the end of the name (includes the unit number) as will
+ * fit. Otherwise, we have multiple handlers and not all of the names
+ * will fit. Add +'s to indicate missing names. If we run out of room
+ * and still have +'s to add, change the last character from a + to a *.
*/
+ if (missed == 1 && space == 1) {
+ ih = CK_SLIST_FIRST(&ie->ie_handlers);
+ missed = strlen(ie->ie_fullname) + strlen(ih->ih_name) + 2 -
+ sizeof(ie->ie_fullname);
+ strcat(ie->ie_fullname, (missed == 0) ? " " : "-");
+ strcat(ie->ie_fullname, &ih->ih_name[missed]);
+ missed = 0;
+ }
last = &ie->ie_fullname[sizeof(ie->ie_fullname) - 2];
while (missed-- > 0) {
if (strlen(ie->ie_fullname) + 1 == sizeof(ie->ie_fullname)) {
diff --git a/freebsd/sys/kern/kern_mib.c b/freebsd/sys/kern/kern_mib.c
index 1933af9a..b1c02570 100644
--- a/freebsd/sys/kern/kern_mib.c
+++ b/freebsd/sys/kern/kern_mib.c
@@ -148,7 +148,7 @@ SYSCTL_INT(_kern, KERN_SAVED_IDS, saved_ids, CTLFLAG_RD|CTLFLAG_CAPRD,
SYSCTL_NULL_INT_PTR, 0, "Whether saved set-group/user ID is available");
#endif
-char kernelname[MAXPATHLEN] = "/kernel"; /* XXX bloat */
+char kernelname[MAXPATHLEN] = "/boot/kernel/kernel"; /* XXX bloat */
SYSCTL_STRING(_kern, KERN_BOOTFILE, bootfile, CTLFLAG_RW | CTLFLAG_MPSAFE,
kernelname, sizeof kernelname, "Name of kernel file booted");
@@ -199,7 +199,8 @@ sysctl_hw_physmem(SYSCTL_HANDLER_ARGS)
return (sysctl_handle_long(oidp, &val, 0, req));
}
SYSCTL_PROC(_hw, HW_PHYSMEM, physmem, CTLTYPE_ULONG | CTLFLAG_RD,
- 0, 0, sysctl_hw_physmem, "LU", "");
+ 0, 0, sysctl_hw_physmem, "LU",
+ "Amount of physical memory (in bytes)");
static int
sysctl_hw_realmem(SYSCTL_HANDLER_ARGS)
@@ -213,7 +214,8 @@ sysctl_hw_realmem(SYSCTL_HANDLER_ARGS)
return (sysctl_handle_long(oidp, &val, 0, req));
}
SYSCTL_PROC(_hw, HW_REALMEM, realmem, CTLTYPE_ULONG | CTLFLAG_RD,
- 0, 0, sysctl_hw_realmem, "LU", "");
+ 0, 0, sysctl_hw_realmem, "LU",
+ "Amount of memory (in bytes) reported by the firmware");
static int
sysctl_hw_usermem(SYSCTL_HANDLER_ARGS)
@@ -228,9 +230,11 @@ sysctl_hw_usermem(SYSCTL_HANDLER_ARGS)
return (sysctl_handle_long(oidp, &val, 0, req));
}
SYSCTL_PROC(_hw, HW_USERMEM, usermem, CTLTYPE_ULONG | CTLFLAG_RD,
- 0, 0, sysctl_hw_usermem, "LU", "");
+ 0, 0, sysctl_hw_usermem, "LU",
+ "Amount of memory (in bytes) which is not wired");
-SYSCTL_LONG(_hw, OID_AUTO, availpages, CTLFLAG_RD, &physmem, 0, "");
+SYSCTL_LONG(_hw, OID_AUTO, availpages, CTLFLAG_RD, &physmem, 0,
+ "Amount of physical memory (in pages)");
u_long pagesizes[MAXPAGESIZES] = { PAGE_SIZE };
diff --git a/freebsd/sys/kern/subr_bus.c b/freebsd/sys/kern/subr_bus.c
index 29fdfe34..8a6b4edf 100644
--- a/freebsd/sys/kern/subr_bus.c
+++ b/freebsd/sys/kern/subr_bus.c
@@ -3040,6 +3040,10 @@ device_detach(device_t dev)
PDEBUG(("%s", DEVICENAME(dev)));
if (dev->state == DS_BUSY)
return (EBUSY);
+ if (dev->state == DS_ATTACHING) {
+ device_printf(dev, "device in attaching state! Deferring detach.\n");
+ return (EBUSY);
+ }
if (dev->state != DS_ATTACHED)
return (0);
@@ -3904,6 +3908,96 @@ bus_generic_resume(device_t dev)
return (0);
}
+
+/**
+ * @brief Helper function for implementing BUS_RESET_POST
+ *
+ * Bus can use this function to implement common operations of
+ * re-attaching or resuming the children after the bus itself was
+ * reset, and after restoring bus-unique state of children.
+ *
+ * @param dev The bus
+ * #param flags DEVF_RESET_*
+ */
+int
+bus_helper_reset_post(device_t dev, int flags)
+{
+ device_t child;
+ int error, error1;
+
+ error = 0;
+ TAILQ_FOREACH(child, &dev->children,link) {
+ BUS_RESET_POST(dev, child);
+ error1 = (flags & DEVF_RESET_DETACH) != 0 ?
+ device_probe_and_attach(child) :
+ BUS_RESUME_CHILD(dev, child);
+ if (error == 0 && error1 != 0)
+ error = error1;
+ }
+ return (error);
+}
+
+static void
+bus_helper_reset_prepare_rollback(device_t dev, device_t child, int flags)
+{
+
+ child = TAILQ_NEXT(child, link);
+ if (child == NULL)
+ return;
+ TAILQ_FOREACH_FROM(child, &dev->children,link) {
+ BUS_RESET_POST(dev, child);
+ if ((flags & DEVF_RESET_DETACH) != 0)
+ device_probe_and_attach(child);
+ else
+ BUS_RESUME_CHILD(dev, child);
+ }
+}
+
+/**
+ * @brief Helper function for implementing BUS_RESET_PREPARE
+ *
+ * Bus can use this function to implement common operations of
+ * detaching or suspending the children before the bus itself is
+ * reset, and then save bus-unique state of children that must
+ * persists around reset.
+ *
+ * @param dev The bus
+ * #param flags DEVF_RESET_*
+ */
+int
+bus_helper_reset_prepare(device_t dev, int flags)
+{
+ device_t child;
+ int error;
+
+ if (dev->state != DS_ATTACHED)
+ return (EBUSY);
+
+ TAILQ_FOREACH_REVERSE(child, &dev->children, device_list, link) {
+ if ((flags & DEVF_RESET_DETACH) != 0) {
+ error = device_get_state(child) == DS_ATTACHED ?
+ device_detach(child) : 0;
+ } else {
+ error = BUS_SUSPEND_CHILD(dev, child);
+ }
+ if (error == 0) {
+ error = BUS_RESET_PREPARE(dev, child);
+ if (error != 0) {
+ if ((flags & DEVF_RESET_DETACH) != 0)
+ device_probe_and_attach(child);
+ else
+ BUS_RESUME_CHILD(dev, child);
+ }
+ }
+ if (error != 0) {
+ bus_helper_reset_prepare_rollback(dev, child, flags);
+ return (error);
+ }
+ }
+ return (0);
+}
+
+
/**
* @brief Helper function for implementing BUS_PRINT_CHILD().
*
@@ -5603,6 +5697,7 @@ devctl2_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
case DEV_CLEAR_DRIVER:
case DEV_RESCAN:
case DEV_DELETE:
+ case DEV_RESET:
error = priv_check(td, PRIV_DRIVER);
if (error == 0)
error = find_device(req, &dev);
@@ -5829,6 +5924,14 @@ devctl2_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
device_frozen = false;
}
break;
+ case DEV_RESET:
+ if ((req->dr_flags & ~(DEVF_RESET_DETACH)) != 0) {
+ error = EINVAL;
+ break;
+ }
+ error = BUS_RESET_CHILD(device_get_parent(dev), dev,
+ req->dr_flags);
+ break;
}
#endif /* __rtems__ */
mtx_unlock(&Giant);
diff --git a/freebsd/sys/net/bpf.c b/freebsd/sys/net/bpf.c
index edee632b..33c58c3e 100644
--- a/freebsd/sys/net/bpf.c
+++ b/freebsd/sys/net/bpf.c
@@ -2695,16 +2695,16 @@ bpfattach2(struct ifnet *ifp, u_int dlt, u_int hdrlen, struct bpf_if **driverp)
{
struct bpf_if *bp;
- bp = malloc(sizeof(*bp), M_BPF, M_NOWAIT | M_ZERO);
- if (bp == NULL)
- panic("bpfattach");
+ KASSERT(*driverp == NULL, ("bpfattach2: driverp already initialized"));
+
+ bp = malloc(sizeof(*bp), M_BPF, M_WAITOK | M_ZERO);
+ rw_init(&bp->bif_lock, "bpf interface lock");
LIST_INIT(&bp->bif_dlist);
LIST_INIT(&bp->bif_wlist);
bp->bif_ifp = ifp;
bp->bif_dlt = dlt;
- rw_init(&bp->bif_lock, "bpf interface lock");
- KASSERT(*driverp == NULL, ("bpfattach2: driverp already initialized"));
+ bp->bif_hdrlen = hdrlen;
bp->bif_bpf = driverp;
*driverp = bp;
@@ -2712,8 +2712,6 @@ bpfattach2(struct ifnet *ifp, u_int dlt, u_int hdrlen, struct bpf_if **driverp)
LIST_INSERT_HEAD(&bpf_iflist, bp, bif_next);
BPF_UNLOCK();
- bp->bif_hdrlen = hdrlen;
-
if (bootverbose && IS_DEFAULT_VNET(curvnet))
if_printf(ifp, "bpf attached\n");
}
diff --git a/freebsd/sys/net/bridgestp.c b/freebsd/sys/net/bridgestp.c
index 49e772b3..b654b04e 100644
--- a/freebsd/sys/net/bridgestp.c
+++ b/freebsd/sys/net/bridgestp.c
@@ -2275,4 +2275,7 @@ bstp_destroy(struct bstp_port *bp)
taskqueue_drain(taskqueue_swi, &bp->bp_statetask);
taskqueue_drain(taskqueue_swi, &bp->bp_rtagetask);
taskqueue_drain(taskqueue_swi, &bp->bp_mediatask);
+
+ if (bp->bp_bs->bs_root_port == bp)
+ bstp_assign_roles(bp->bp_bs);
}
diff --git a/freebsd/sys/net/ethernet.h b/freebsd/sys/net/ethernet.h
index fa75c1df..0753e31d 100644
--- a/freebsd/sys/net/ethernet.h
+++ b/freebsd/sys/net/ethernet.h
@@ -422,6 +422,7 @@ void ether_vlan_mtap(struct bpf_if *, struct mbuf *,
struct mbuf *ether_vlanencap(struct mbuf *, uint16_t);
bool ether_8021q_frame(struct mbuf **mp, struct ifnet *ife, struct ifnet *p,
uint16_t vid, uint8_t pcp);
+void ether_gen_addr(struct ifnet *ifp, struct ether_addr *hwaddr);
#ifdef _SYS_EVENTHANDLER_H_
/* new ethernet interface attached event */
diff --git a/freebsd/sys/net/ieee_oui.h b/freebsd/sys/net/ieee_oui.h
new file mode 100644
index 00000000..f543f561
--- /dev/null
+++ b/freebsd/sys/net/ieee_oui.h
@@ -0,0 +1,80 @@
+/* -
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ *
+ * Author: George V. Neville-Neil
+ *
+ */
+
+/* Organizationally Unique Identifier assigned by IEEE 14 Nov 2013 */
+#define OUI_FREEBSD_BASE 0x589cfc000000
+#define OUI_FREEBSD(nic) (OUI_FREEBSD_BASE | (nic))
+
+/*
+ * OUIs are most often used to uniquely identify network interfaces
+ * and occupy the first 3 bytes of both destination and source MAC
+ * addresses. The following allocations exist so that various
+ * software systems associated with FreeBSD can have unique IDs in the
+ * absence of hardware. The use of OUIs for this purpose is not fully
+ * fleshed out but is now in common use in virtualization technology.
+ *
+ * Allocations from this range are expected to be made using COMMON
+ * SENSE by developers. Do NOT take a large range just because
+ * they're currently wide open. Take the smallest useful range for
+ * your system. We have (2^24 - 2) available addresses (see Reserved
+ * Values below) but that is far from infinite.
+ *
+ * In the event of a conflict arbitration of allocation in this file
+ * is subject to core@ approval.
+ *
+ * Applications are differentiated based on the high order bit(s) of
+ * the remaining three bytes. Our first allocation has all 0s, the
+ * next allocation has the highest bit set. Allocating in this way
+ * gives us 254 allocations of 64K addresses. Address blocks can be
+ * concatenated if necessary.
+ *
+ * Reserved Values: 0x000000 and 0xffffff are reserved and MUST NOT BE
+ * allocated for any reason.
+ */
+
+/* Allocate 20 bits to bhyve */
+#define OUI_FREEBSD_BHYVE_LOW OUI_FREEBSD(0x000001)
+#define OUI_FREEBSD_BHYVE_HIGH OUI_FREEBSD(0x0fffff)
+
+/*
+ * Allocate 16 bits for a pool to give to various interfaces that need a
+ * generated address, but don't quite need to slice off a whole section of
+ * the OUI (e.g. cloned interfaces, one-off NICs of various vendors).
+ *
+ * ether_gen_addr should be used to generate an address from this pool.
+ */
+#define OUI_FREEBSD_GENERATED_MASK 0x10ffff
+#define OUI_FREEBSD_GENERATED_LOW OUI_FREEBSD(0x100000)
+#define OUI_FREEBSD_GENERATED_HIGH OUI_FREEBSD(OU_FREEBSD_GENERATED_MASK)
diff --git a/freebsd/sys/net/if.c b/freebsd/sys/net/if.c
index 588753f9..5f0329fd 100644
--- a/freebsd/sys/net/if.c
+++ b/freebsd/sys/net/if.c
@@ -64,6 +64,8 @@
#include <sys/domain.h>
#include <sys/jail.h>
#include <sys/priv.h>
+#include <sys/sched.h>
+#include <sys/smp.h>
#include <machine/stdarg.h>
#include <vm/uma.h>
@@ -1763,6 +1765,32 @@ if_data_copy(struct ifnet *ifp, struct if_data *ifd)
ifd->ifi_noproto = ifp->if_get_counter(ifp, IFCOUNTER_NOPROTO);
}
+#ifndef __rtems__
+struct ifnet_read_lock {
+ struct mtx mtx; /* lock protecting tracker below */
+ struct epoch_tracker et;
+};
+
+DPCPU_DEFINE_STATIC(struct ifnet_read_lock, ifnet_addr_read_lock);
+DPCPU_DEFINE_STATIC(struct ifnet_read_lock, ifnet_maddr_read_lock);
+
+static void
+ifnet_read_lock_init(void __unused *arg)
+{
+ struct ifnet_read_lock *pifrl;
+ int cpu;
+
+ CPU_FOREACH(cpu) {
+ pifrl = DPCPU_ID_PTR(cpu, ifnet_addr_read_lock);
+ mtx_init(&pifrl->mtx, "ifnet_addr_read_lock", NULL, MTX_DEF);
+
+ pifrl = DPCPU_ID_PTR(cpu, ifnet_maddr_read_lock);
+ mtx_init(&pifrl->mtx, "ifnet_maddr_read_lock", NULL, MTX_DEF);
+ }
+}
+SYSINIT(ifnet_read_lock_init, SI_SUB_CPU + 1, SI_ORDER_FIRST, &ifnet_read_lock_init, NULL);
+#endif /* __rtems__ */
+
/*
* Wrapper functions for struct ifnet address list locking macros. These are
* used by kernel modules to avoid encoding programming interface or binary
@@ -1772,35 +1800,63 @@ if_data_copy(struct ifnet *ifp, struct if_data *ifd)
void
if_addr_rlock(struct ifnet *ifp)
{
- MPASS(*(uint64_t *)&ifp->if_addr_et == 0);
- epoch_enter_preempt(net_epoch_preempt, &ifp->if_addr_et);
+#ifndef __rtems__
+ struct ifnet_read_lock *pifrl;
+
+ sched_pin();
+ pifrl = DPCPU_PTR(ifnet_addr_read_lock);
+ mtx_lock(&pifrl->mtx);
+ epoch_enter_preempt(net_epoch_preempt, &pifrl->et);
+#else /* __rtems__ */
+ epoch_enter_preempt(net_epoch_preempt, curthread->td_et);
+#endif /* __rtems__ */
}
void
if_addr_runlock(struct ifnet *ifp)
{
- epoch_exit_preempt(net_epoch_preempt, &ifp->if_addr_et);
-#ifdef INVARIANTS
- bzero(&ifp->if_addr_et, sizeof(struct epoch_tracker));
-#endif
+#ifndef __rtems__
+ struct ifnet_read_lock *pifrl;
+
+ pifrl = DPCPU_PTR(ifnet_addr_read_lock);
+
+ epoch_exit_preempt(net_epoch_preempt, &pifrl->et);
+ mtx_unlock(&pifrl->mtx);
+ sched_unpin();
+#else /* __rtems__ */
+ epoch_exit_preempt(net_epoch_preempt, curthread->td_et);
+#endif /* __rtems__ */
}
void
if_maddr_rlock(if_t ifp)
{
+#ifndef __rtems__
+ struct ifnet_read_lock *pifrl;
- MPASS(*(uint64_t *)&ifp->if_maddr_et == 0);
- epoch_enter_preempt(net_epoch_preempt, &ifp->if_maddr_et);
+ sched_pin();
+ pifrl = DPCPU_PTR(ifnet_maddr_read_lock);
+ mtx_lock(&pifrl->mtx);
+ epoch_enter_preempt(net_epoch_preempt, &pifrl->et);
+#else /* __rtems__ */
+ epoch_enter_preempt(net_epoch_preempt, curthread->td_et);
+#endif /* __rtems__ */
}
void
if_maddr_runlock(if_t ifp)
{
+#ifndef __rtems__
+ struct ifnet_read_lock *pifrl;
- epoch_exit_preempt(net_epoch_preempt, &ifp->if_maddr_et);
-#ifdef INVARIANTS
- bzero(&ifp->if_maddr_et, sizeof(struct epoch_tracker));
-#endif
+ pifrl = DPCPU_PTR(ifnet_maddr_read_lock);
+
+ epoch_exit_preempt(net_epoch_preempt, &pifrl->et);
+ mtx_unlock(&pifrl->mtx);
+ sched_unpin();
+#else /* __rtems__ */
+ epoch_exit_preempt(net_epoch_preempt, curthread->td_et);
+#endif /* __rtems__ */
}
/*
diff --git a/freebsd/sys/net/if_bridge.c b/freebsd/sys/net/if_bridge.c
index b5e231b8..4bfb67a8 100644
--- a/freebsd/sys/net/if_bridge.c
+++ b/freebsd/sys/net/if_bridge.c
@@ -228,7 +228,7 @@ struct bridge_softc {
struct bstp_state sc_stp; /* STP state */
uint32_t sc_brtexceeded; /* # of cache drops */
struct ifnet *sc_ifaddr; /* member mac copied from */
- u_char sc_defaddr[6]; /* Default MAC address */
+ struct ether_addr sc_defaddr; /* Default MAC address */
};
VNET_DEFINE_STATIC(struct mtx, bridge_list_mtx);
@@ -237,7 +237,8 @@ static eventhandler_tag bridge_detach_cookie;
int bridge_rtable_prune_period = BRIDGE_RTABLE_PRUNE_PERIOD;
-uma_zone_t bridge_rtnode_zone;
+VNET_DEFINE_STATIC(uma_zone_t, bridge_rtnode_zone);
+#define V_bridge_rtnode_zone VNET(bridge_rtnode_zone)
static int bridge_clone_create(struct if_clone *, int, caddr_t);
static void bridge_clone_destroy(struct ifnet *);
@@ -529,6 +530,9 @@ static void
vnet_bridge_init(const void *unused __unused)
{
+ V_bridge_rtnode_zone = uma_zcreate("bridge_rtnode",
+ sizeof(struct bridge_rtnode), NULL, NULL, NULL, NULL,
+ UMA_ALIGN_PTR, 0);
BRIDGE_LIST_LOCK_INIT();
LIST_INIT(&V_bridge_list);
V_bridge_cloner = if_clone_simple(bridge_name,
@@ -544,6 +548,7 @@ vnet_bridge_uninit(const void *unused __unused)
if_clone_detach(V_bridge_cloner);
V_bridge_cloner = NULL;
BRIDGE_LIST_LOCK_DESTROY();
+ uma_zdestroy(V_bridge_rtnode_zone);
}
VNET_SYSUNINIT(vnet_bridge_uninit, SI_SUB_PSEUDO, SI_ORDER_ANY,
vnet_bridge_uninit, NULL);
@@ -554,9 +559,6 @@ bridge_modevent(module_t mod, int type, void *data)
switch (type) {
case MOD_LOAD:
- bridge_rtnode_zone = uma_zcreate("bridge_rtnode",
- sizeof(struct bridge_rtnode), NULL, NULL, NULL, NULL,
- UMA_ALIGN_PTR, 0);
bridge_dn_p = bridge_dummynet;
bridge_detach_cookie = EVENTHANDLER_REGISTER(
ifnet_departure_event, bridge_ifdetach, NULL,
@@ -565,7 +567,6 @@ bridge_modevent(module_t mod, int type, void *data)
case MOD_UNLOAD:
EVENTHANDLER_DEREGISTER(ifnet_departure_event,
bridge_detach_cookie);
- uma_zdestroy(bridge_rtnode_zone);
bridge_dn_p = NULL;
break;
default:
@@ -672,16 +673,14 @@ bridge_clone_create(struct if_clone *ifc, int unit, caddr_t params)
getcredhostid(curthread->td_ucred, &hostid);
do {
if (fb || hostid == 0) {
- arc4rand(sc->sc_defaddr, ETHER_ADDR_LEN, 1);
- sc->sc_defaddr[0] &= ~1;/* clear multicast bit */
- sc->sc_defaddr[0] |= 2; /* set the LAA bit */
+ ether_gen_addr(ifp, &sc->sc_defaddr);
} else {
- sc->sc_defaddr[0] = 0x2;
- sc->sc_defaddr[1] = (hostid >> 24) & 0xff;
- sc->sc_defaddr[2] = (hostid >> 16) & 0xff;
- sc->sc_defaddr[3] = (hostid >> 8 ) & 0xff;
- sc->sc_defaddr[4] = hostid & 0xff;
- sc->sc_defaddr[5] = ifp->if_dunit & 0xff;
+ sc->sc_defaddr.octet[0] = 0x2;
+ sc->sc_defaddr.octet[1] = (hostid >> 24) & 0xff;
+ sc->sc_defaddr.octet[2] = (hostid >> 16) & 0xff;
+ sc->sc_defaddr.octet[3] = (hostid >> 8 ) & 0xff;
+ sc->sc_defaddr.octet[4] = hostid & 0xff;
+ sc->sc_defaddr.octet[5] = ifp->if_dunit & 0xff;
}
fb = 1;
@@ -689,7 +688,7 @@ bridge_clone_create(struct if_clone *ifc, int unit, caddr_t params)
BRIDGE_LIST_LOCK();
LIST_FOREACH(sc2, &V_bridge_list, sc_list) {
bifp = sc2->sc_ifp;
- if (memcmp(sc->sc_defaddr,
+ if (memcmp(sc->sc_defaddr.octet,
IF_LLADDR(bifp), ETHER_ADDR_LEN) == 0) {
retry = 1;
break;
@@ -699,7 +698,7 @@ bridge_clone_create(struct if_clone *ifc, int unit, caddr_t params)
} while (retry == 1);
bstp_attach(&sc->sc_stp, &bridge_ops);
- ether_ifattach(ifp, sc->sc_defaddr);
+ ether_ifattach(ifp, sc->sc_defaddr.octet);
/* Now undo some of the damage... */
ifp->if_baudrate = 0;
ifp->if_type = IFT_BRIDGE;
@@ -734,6 +733,9 @@ bridge_clone_destroy(struct ifnet *ifp)
bridge_delete_span(sc, bif);
}
+ /* Tear down the routing table. */
+ bridge_rtable_fini(sc);
+
BRIDGE_UNLOCK(sc);
callout_drain(&sc->sc_brcallout);
@@ -746,9 +748,6 @@ bridge_clone_destroy(struct ifnet *ifp)
ether_ifdetach(ifp);
if_free(ifp);
- /* Tear down the routing table. */
- bridge_rtable_fini(sc);
-
BRIDGE_LOCK_DESTROY(sc);
free(sc, M_DEVBUF);
}
@@ -1020,7 +1019,7 @@ bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif,
*/
if (V_bridge_inherit_mac && sc->sc_ifaddr == ifs) {
if (LIST_EMPTY(&sc->sc_iflist)) {
- bcopy(sc->sc_defaddr,
+ bcopy(&sc->sc_defaddr,
IF_LLADDR(sc->sc_ifp), ETHER_ADDR_LEN);
sc->sc_ifaddr = NULL;
} else {
@@ -1191,7 +1190,7 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg)
* the default randomly generated one.
*/
if (V_bridge_inherit_mac && LIST_EMPTY(&sc->sc_iflist) &&
- !memcmp(IF_LLADDR(sc->sc_ifp), sc->sc_defaddr, ETHER_ADDR_LEN)) {
+ !memcmp(IF_LLADDR(sc->sc_ifp), sc->sc_defaddr.octet, ETHER_ADDR_LEN)) {
bcopy(IF_LLADDR(ifs), IF_LLADDR(sc->sc_ifp), ETHER_ADDR_LEN);
sc->sc_ifaddr = ifs;
EVENTHANDLER_INVOKE(iflladdr_event, sc->sc_ifp);
@@ -2673,7 +2672,7 @@ bridge_rtupdate(struct bridge_softc *sc, const uint8_t *dst, uint16_t vlan,
* initialize the expiration time and Ethernet
* address.
*/
- brt = uma_zalloc(bridge_rtnode_zone, M_NOWAIT | M_ZERO);
+ brt = uma_zalloc(V_bridge_rtnode_zone, M_NOWAIT | M_ZERO);
if (brt == NULL)
return (ENOMEM);
@@ -2686,7 +2685,7 @@ bridge_rtupdate(struct bridge_softc *sc, const uint8_t *dst, uint16_t vlan,
brt->brt_vlan = vlan;
if ((error = bridge_rtnode_insert(sc, brt)) != 0) {
- uma_zfree(bridge_rtnode_zone, brt);
+ uma_zfree(V_bridge_rtnode_zone, brt);
return (error);
}
brt->brt_dst = bif;
@@ -2770,11 +2769,14 @@ bridge_timer(void *arg)
BRIDGE_LOCK_ASSERT(sc);
+ /* Destruction of rtnodes requires a proper vnet context */
+ CURVNET_SET(sc->sc_ifp->if_vnet);
bridge_rtage(sc);
if (sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING)
callout_reset(&sc->sc_brcallout,
bridge_rtable_prune_period * hz, bridge_timer, sc);
+ CURVNET_RESTORE();
}
/*
@@ -3032,7 +3034,7 @@ bridge_rtnode_destroy(struct bridge_softc *sc, struct bridge_rtnode *brt)
LIST_REMOVE(brt, brt_list);
sc->sc_brtcnt--;
brt->brt_dst->bif_addrcnt--;
- uma_zfree(bridge_rtnode_zone, brt);
+ uma_zfree(V_bridge_rtnode_zone, brt);
}
/*
@@ -3046,6 +3048,7 @@ bridge_rtable_expire(struct ifnet *ifp, int age)
struct bridge_softc *sc = ifp->if_bridge;
struct bridge_rtnode *brt;
+ CURVNET_SET(ifp->if_vnet);
BRIDGE_LOCK(sc);
/*
@@ -3064,6 +3067,7 @@ bridge_rtable_expire(struct ifnet *ifp, int age)
}
}
BRIDGE_UNLOCK(sc);
+ CURVNET_RESTORE();
}
/*
diff --git a/freebsd/sys/net/if_ethersubr.c b/freebsd/sys/net/if_ethersubr.c
index 01e757e5..70b26160 100644
--- a/freebsd/sys/net/if_ethersubr.c
+++ b/freebsd/sys/net/if_ethersubr.c
@@ -44,11 +44,13 @@
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/eventhandler.h>
+#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/mbuf.h>
+#include <sys/proc.h>
#include <sys/priv.h>
#include <sys/random.h>
#include <sys/socket.h>
@@ -56,6 +58,7 @@
#include <sys/sysctl.h>
#include <sys/uuid.h>
+#include <net/ieee_oui.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_arp.h>
@@ -87,6 +90,8 @@
#endif
#include <security/mac/mac_framework.h>
+#include <crypto/sha1.h>
+
#ifdef CTASSERT
CTASSERT(sizeof (struct ether_header) == ETHER_ADDR_LEN * 2 + 2);
CTASSERT(sizeof (struct ether_addr) == ETHER_ADDR_LEN);
@@ -1370,5 +1375,38 @@ ether_8021q_frame(struct mbuf **mp, struct ifnet *ife, struct ifnet *p,
return (true);
}
+/*
+ * Allocate an address from the FreeBSD Foundation OUI. This uses a
+ * cryptographic hash function on the containing jail's UUID and the interface
+ * name to attempt to provide a unique but stable address. Pseudo-interfaces
+ * which require a MAC address should use this function to allocate
+ * non-locally-administered addresses.
+ */
+void
+ether_gen_addr(struct ifnet *ifp, struct ether_addr *hwaddr)
+{
+#define ETHER_GEN_ADDR_BUFSIZ HOSTUUIDLEN + IFNAMSIZ + 2
+ SHA1_CTX ctx;
+ char buf[ETHER_GEN_ADDR_BUFSIZ];
+ char uuid[HOSTUUIDLEN + 1];
+ uint64_t addr;
+ int i, sz;
+ char digest[SHA1_RESULTLEN];
+
+ getcredhostuuid(curthread->td_ucred, uuid, sizeof(uuid));
+ sz = snprintf(buf, ETHER_GEN_ADDR_BUFSIZ, "%s-%s", uuid, ifp->if_xname);
+ SHA1Init(&ctx);
+ SHA1Update(&ctx, buf, sz);
+ SHA1Final(digest, &ctx);
+
+ addr = ((digest[0] << 16) | (digest[1] << 8) | digest[2]) &
+ OUI_FREEBSD_GENERATED_MASK;
+ addr = OUI_FREEBSD(addr);
+ for (i = 0; i < ETHER_ADDR_LEN; ++i) {
+ hwaddr->octet[i] = addr >> ((ETHER_ADDR_LEN - i - 1) * 8) &
+ 0xFF;
+ }
+}
+
DECLARE_MODULE(ether, ether_mod, SI_SUB_INIT_IF, SI_ORDER_ANY);
MODULE_VERSION(ether, 1);
diff --git a/freebsd/sys/net/if_gre.c b/freebsd/sys/net/if_gre.c
index 4fbc105e..5aeb8266 100644
--- a/freebsd/sys/net/if_gre.c
+++ b/freebsd/sys/net/if_gre.c
@@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
#include <rtems/bsd/local/opt_inet.h>
#include <rtems/bsd/local/opt_inet6.h>
+#include <rtems/bsd/local/opt_rss.h>
#include <sys/param.h>
#include <sys/kernel.h>
@@ -51,6 +52,7 @@ __FBSDID("$FreeBSD$");
#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/socket.h>
+#include <sys/socketvar.h>
#include <sys/sockio.h>
#include <sys/sx.h>
#include <sys/sysctl.h>
@@ -67,19 +69,27 @@ __FBSDID("$FreeBSD$");
#include <net/route.h>
#include <netinet/in.h>
+#include <netinet/in_pcb.h>
#ifdef INET
#include <netinet/in_var.h>
#include <netinet/ip.h>
#include <netinet/ip_var.h>
+#ifdef RSS
+#include <netinet/in_rss.h>
+#endif
#endif
#ifdef INET6
#include <netinet/ip6.h>
#include <netinet6/in6_var.h>
#include <netinet6/ip6_var.h>
+#ifdef RSS
+#include <netinet6/in6_rss.h>
+#endif
#endif
#include <netinet/ip_encap.h>
+#include <netinet/udp.h>
#include <net/bpf.h>
#include <net/if_gre.h>
@@ -153,6 +163,7 @@ vnet_gre_uninit(const void *unused __unused)
#ifdef INET6
in6_gre_uninit();
#endif
+ /* XXX: epoch_call drain */
}
VNET_SYSUNINIT(vnet_gre_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
vnet_gre_uninit, NULL);
@@ -272,6 +283,7 @@ gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
break;
case GRESKEY:
case GRESOPTS:
+ case GRESPORT:
if ((error = priv_check(curthread, PRIV_NET_GRE)) != 0)
break;
if ((error = copyin(ifr_data_get_ptr(ifr), &opt,
@@ -287,23 +299,45 @@ gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
}
if (sc->gre_options == opt)
break;
+ } else if (cmd == GRESPORT) {
+ if (opt != 0 && (opt < V_ipport_hifirstauto ||
+ opt > V_ipport_hilastauto)) {
+ error = EINVAL;
+ break;
+ }
+ if (sc->gre_port == opt)
+ break;
+ if ((sc->gre_options & GRE_UDPENCAP) == 0) {
+ /*
+ * UDP encapsulation is not enabled, thus
+ * there is no need to reattach softc.
+ */
+ sc->gre_port = opt;
+ break;
+ }
}
switch (sc->gre_family) {
#ifdef INET
case AF_INET:
- in_gre_setopts(sc, cmd, opt);
+ error = in_gre_setopts(sc, cmd, opt);
break;
#endif
#ifdef INET6
case AF_INET6:
- in6_gre_setopts(sc, cmd, opt);
+ error = in6_gre_setopts(sc, cmd, opt);
break;
#endif
default:
+ /*
+ * Tunnel is not yet configured.
+ * We can just change any parameters.
+ */
if (cmd == GRESKEY)
sc->gre_key = opt;
- else
+ if (cmd == GRESOPTS)
sc->gre_options = opt;
+ if (cmd == GRESPORT)
+ sc->gre_port = opt;
break;
}
/*
@@ -319,6 +353,10 @@ gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
error = copyout(&sc->gre_options, ifr_data_get_ptr(ifr),
sizeof(sc->gre_options));
break;
+ case GREGPORT:
+ error = copyout(&sc->gre_port, ifr_data_get_ptr(ifr),
+ sizeof(sc->gre_port));
+ break;
default:
error = EINVAL;
break;
@@ -343,6 +381,7 @@ end:
static void
gre_delete_tunnel(struct gre_softc *sc)
{
+ struct gre_socket *gs;
sx_assert(&gre_ioctl_sx, SA_XLOCKED);
if (sc->gre_family != 0) {
@@ -352,6 +391,16 @@ gre_delete_tunnel(struct gre_softc *sc)
free(sc->gre_hdr, M_GRE);
sc->gre_family = 0;
}
+ /*
+ * If this Tunnel was the last one that could use UDP socket,
+ * we should unlink socket from hash table and close it.
+ */
+ if ((gs = sc->gre_so) != NULL && CK_LIST_EMPTY(&gs->list)) {
+ CK_LIST_REMOVE(gs, chain);
+ soclose(gs->so);
+ epoch_call(net_epoch_preempt, &gs->epoch_ctx, gre_sofree);
+ sc->gre_so = NULL;
+ }
GRE2IFP(sc)->if_drv_flags &= ~IFF_DRV_RUNNING;
if_link_state_change(GRE2IFP(sc), LINK_STATE_DOWN);
}
@@ -378,7 +427,38 @@ gre_hashdestroy(struct gre_list *hash)
}
void
-gre_updatehdr(struct gre_softc *sc, struct grehdr *gh)
+gre_sofree(epoch_context_t ctx)
+{
+ struct gre_socket *gs;
+
+ gs = __containerof(ctx, struct gre_socket, epoch_ctx);
+ free(gs, M_GRE);
+}
+
+static __inline uint16_t
+gre_cksum_add(uint16_t sum, uint16_t a)
+{
+ uint16_t res;
+
+ res = sum + a;
+ return (res + (res < a));
+}
+
+void
+gre_update_udphdr(struct gre_softc *sc, struct udphdr *udp, uint16_t csum)
+{
+
+ sx_assert(&gre_ioctl_sx, SA_XLOCKED);
+ MPASS(sc->gre_options & GRE_UDPENCAP);
+
+ udp->uh_dport = htons(GRE_UDPPORT);
+ udp->uh_sport = htons(sc->gre_port);
+ udp->uh_sum = csum;
+ udp->uh_ulen = 0;
+}
+
+void
+gre_update_hdr(struct gre_softc *sc, struct grehdr *gh)
{
uint32_t *opts;
uint16_t flags;
@@ -545,6 +625,52 @@ gre_setseqn(struct grehdr *gh, uint32_t seq)
*opts = htonl(seq);
}
+static uint32_t
+gre_flowid(struct gre_softc *sc, struct mbuf *m, uint32_t af)
+{
+ uint32_t flowid;
+
+ if ((sc->gre_options & GRE_UDPENCAP) == 0 || sc->gre_port != 0)
+ return (0);
+#ifndef RSS
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+ flowid = mtod(m, struct ip *)->ip_src.s_addr ^
+ mtod(m, struct ip *)->ip_dst.s_addr;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ flowid = mtod(m, struct ip6_hdr *)->ip6_src.s6_addr32[3] ^
+ mtod(m, struct ip6_hdr *)->ip6_dst.s6_addr32[3];
+ break;
+#endif
+ default:
+ flowid = 0;
+ }
+#else /* RSS */
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+ flowid = rss_hash_ip4_2tuple(mtod(m, struct ip *)->ip_src,
+ mtod(m, struct ip *)->ip_dst);
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ flowid = rss_hash_ip6_2tuple(
+ &mtod(m, struct ip6_hdr *)->ip6_src,
+ &mtod(m, struct ip6_hdr *)->ip6_dst);
+ break;
+#endif
+ default:
+ flowid = 0;
+ }
+#endif
+ return (flowid);
+}
+
#define MTAG_GRE 1307983903
static int
gre_transmit(struct ifnet *ifp, struct mbuf *m)
@@ -552,7 +678,8 @@ gre_transmit(struct ifnet *ifp, struct mbuf *m)
GRE_RLOCK_TRACKER;
struct gre_softc *sc;
struct grehdr *gh;
- uint32_t af;
+ struct udphdr *uh;
+ uint32_t af, flowid;
int error, len;
uint16_t proto;
@@ -579,6 +706,7 @@ gre_transmit(struct ifnet *ifp, struct mbuf *m)
af = m->m_pkthdr.csum_data;
BPF_MTAP2(ifp, &af, sizeof(af), m);
m->m_flags &= ~(M_BCAST|M_MCAST);
+ flowid = gre_flowid(sc, m, af);
M_SETFIB(m, sc->gre_fibnum);
M_PREPEND(m, sc->gre_hlen, M_NOWAIT);
if (m == NULL) {
@@ -620,6 +748,19 @@ gre_transmit(struct ifnet *ifp, struct mbuf *m)
error = ENETDOWN;
goto drop;
}
+ if (sc->gre_options & GRE_UDPENCAP) {
+ uh = (struct udphdr *)mtodo(m, len);
+ uh->uh_sport |= htons(V_ipport_hifirstauto) |
+ (flowid >> 16) | (flowid & 0xFFFF);
+ uh->uh_sport = htons(ntohs(uh->uh_sport) %
+ V_ipport_hilastauto);
+ uh->uh_ulen = htons(m->m_pkthdr.len - len);
+ uh->uh_sum = gre_cksum_add(uh->uh_sum,
+ htons(m->m_pkthdr.len - len + IPPROTO_UDP));
+ m->m_pkthdr.csum_flags = sc->gre_csumflags;
+ m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum);
+ len += sizeof(struct udphdr);
+ }
gh = (struct grehdr *)mtodo(m, len);
gh->gre_proto = proto;
if (sc->gre_options & GRE_ENABLE_SEQ)
@@ -637,7 +778,7 @@ gre_transmit(struct ifnet *ifp, struct mbuf *m)
#endif
#ifdef INET6
case AF_INET6:
- error = in6_gre_output(m, af, sc->gre_hlen);
+ error = in6_gre_output(m, af, sc->gre_hlen, flowid);
break;
#endif
default:
diff --git a/freebsd/sys/net/if_gre.h b/freebsd/sys/net/if_gre.h
index 4b93321a..de3c5979 100644
--- a/freebsd/sys/net/if_gre.h
+++ b/freebsd/sys/net/if_gre.h
@@ -53,14 +53,35 @@ struct greip {
struct ip gi_ip;
struct grehdr gi_gre;
} __packed;
-#endif
+
+struct greudp {
+ struct ip gi_ip;
+ struct udphdr gi_udp;
+ struct grehdr gi_gre;
+} __packed;
+#endif /* INET */
#ifdef INET6
struct greip6 {
struct ip6_hdr gi6_ip6;
struct grehdr gi6_gre;
} __packed;
-#endif
+
+struct greudp6 {
+ struct ip6_hdr gi6_ip6;
+ struct udphdr gi6_udp;
+ struct grehdr gi6_gre;
+} __packed;
+#endif /* INET6 */
+
+CK_LIST_HEAD(gre_list, gre_softc);
+CK_LIST_HEAD(gre_sockets, gre_socket);
+struct gre_socket {
+ struct socket *so;
+ struct gre_list list;
+ CK_LIST_ENTRY(gre_socket) chain;
+ struct epoch_context epoch_ctx;
+};
struct gre_softc {
struct ifnet *gre_ifp;
@@ -69,22 +90,26 @@ struct gre_softc {
uint32_t gre_oseq;
uint32_t gre_key;
uint32_t gre_options;
+ uint32_t gre_csumflags;
+ uint32_t gre_port;
u_int gre_fibnum;
u_int gre_hlen; /* header size */
union {
void *hdr;
#ifdef INET
- struct greip *gihdr;
+ struct greip *iphdr;
+ struct greudp *udphdr;
#endif
#ifdef INET6
- struct greip6 *gi6hdr;
+ struct greip6 *ip6hdr;
+ struct greudp6 *udp6hdr;
#endif
} gre_uhdr;
+ struct gre_socket *gre_so;
CK_LIST_ENTRY(gre_softc) chain;
CK_LIST_ENTRY(gre_softc) srchash;
};
-CK_LIST_HEAD(gre_list, gre_softc);
MALLOC_DECLARE(M_GRE);
#ifndef GRE_HASH_SIZE
@@ -98,28 +123,35 @@ MALLOC_DECLARE(M_GRE);
#define GRE_WAIT() epoch_wait_preempt(net_epoch_preempt)
#define gre_hdr gre_uhdr.hdr
-#define gre_gihdr gre_uhdr.gihdr
-#define gre_gi6hdr gre_uhdr.gi6hdr
-#define gre_oip gre_gihdr->gi_ip
-#define gre_oip6 gre_gi6hdr->gi6_ip6
+#define gre_iphdr gre_uhdr.iphdr
+#define gre_ip6hdr gre_uhdr.ip6hdr
+#define gre_udphdr gre_uhdr.udphdr
+#define gre_udp6hdr gre_uhdr.udp6hdr
+
+#define gre_oip gre_iphdr->gi_ip
+#define gre_udp gre_udphdr->gi_udp
+#define gre_oip6 gre_ip6hdr->gi6_ip6
+#define gre_udp6 gre_udp6hdr->gi6_udp
struct gre_list *gre_hashinit(void);
void gre_hashdestroy(struct gre_list *);
int gre_input(struct mbuf *, int, int, void *);
-void gre_updatehdr(struct gre_softc *, struct grehdr *);
+void gre_update_hdr(struct gre_softc *, struct grehdr *);
+void gre_update_udphdr(struct gre_softc *, struct udphdr *, uint16_t);
+void gre_sofree(epoch_context_t);
void in_gre_init(void);
void in_gre_uninit(void);
-void in_gre_setopts(struct gre_softc *, u_long, uint32_t);
+int in_gre_setopts(struct gre_softc *, u_long, uint32_t);
int in_gre_ioctl(struct gre_softc *, u_long, caddr_t);
int in_gre_output(struct mbuf *, int, int);
void in6_gre_init(void);
void in6_gre_uninit(void);
-void in6_gre_setopts(struct gre_softc *, u_long, uint32_t);
+int in6_gre_setopts(struct gre_softc *, u_long, uint32_t);
int in6_gre_ioctl(struct gre_softc *, u_long, caddr_t);
-int in6_gre_output(struct mbuf *, int, int);
+int in6_gre_output(struct mbuf *, int, int, uint32_t);
/*
* CISCO uses special type for GRE tunnel created as part of WCCP
* connection, while in fact those packets are just IPv4 encapsulated
@@ -139,9 +171,15 @@ int in6_gre_output(struct mbuf *, int, int);
#define GRESKEY _IOW('i', 108, struct ifreq)
#define GREGOPTS _IOWR('i', 109, struct ifreq)
#define GRESOPTS _IOW('i', 110, struct ifreq)
+#define GREGPORT _IOWR('i', 111, struct ifreq)
+#define GRESPORT _IOW('i', 112, struct ifreq)
+
+/* GRE-in-UDP encapsulation destination port as defined in RFC8086 */
+#define GRE_UDPPORT 4754
#define GRE_ENABLE_CSUM 0x0001
#define GRE_ENABLE_SEQ 0x0002
-#define GRE_OPTMASK (GRE_ENABLE_CSUM|GRE_ENABLE_SEQ)
+#define GRE_UDPENCAP 0x0004
+#define GRE_OPTMASK (GRE_ENABLE_CSUM|GRE_ENABLE_SEQ|GRE_UDPENCAP)
#endif /* _NET_IF_GRE_H_ */
diff --git a/freebsd/sys/net/if_lagg.c b/freebsd/sys/net/if_lagg.c
index c9c1e8f9..af6f1667 100644
--- a/freebsd/sys/net/if_lagg.c
+++ b/freebsd/sys/net/if_lagg.c
@@ -113,6 +113,7 @@ static void lagg_clone_destroy(struct ifnet *);
VNET_DEFINE_STATIC(struct if_clone *, lagg_cloner);
#define V_lagg_cloner VNET(lagg_cloner)
static const char laggname[] = "lagg";
+static MALLOC_DEFINE(M_LAGG, laggname, "802.3AD Link Aggregation Interface");
static void lagg_capabilities(struct lagg_softc *);
static int lagg_port_create(struct lagg_softc *, struct ifnet *);
@@ -480,10 +481,10 @@ lagg_clone_create(struct if_clone *ifc, int unit, caddr_t params)
struct ifnet *ifp;
static const u_char eaddr[6]; /* 00:00:00:00:00:00 */
- sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO);
+ sc = malloc(sizeof(*sc), M_LAGG, M_WAITOK|M_ZERO);
ifp = sc->sc_ifp = if_alloc(IFT_ETHER);
if (ifp == NULL) {
- free(sc, M_DEVBUF);
+ free(sc, M_LAGG);
return (ENOSPC);
}
LAGG_SX_INIT(sc);
@@ -570,7 +571,7 @@ lagg_clone_destroy(struct ifnet *ifp)
LAGG_LIST_UNLOCK();
LAGG_SX_DESTROY(sc);
- free(sc, M_DEVBUF);
+ free(sc, M_LAGG);
}
static void
@@ -684,7 +685,7 @@ lagg_port_create(struct lagg_softc *sc, struct ifnet *ifp)
ifr.ifr_mtu = oldmtu;
}
- lp = malloc(sizeof(struct lagg_port), M_DEVBUF, M_WAITOK|M_ZERO);
+ lp = malloc(sizeof(struct lagg_port), M_LAGG, M_WAITOK|M_ZERO);
lp->lp_softc = sc;
/* Check if port is a stacked lagg */
@@ -692,7 +693,7 @@ lagg_port_create(struct lagg_softc *sc, struct ifnet *ifp)
SLIST_FOREACH(sc_ptr, &V_lagg_list, sc_entries) {
if (ifp == sc_ptr->sc_ifp) {
LAGG_LIST_UNLOCK();
- free(lp, M_DEVBUF);
+ free(lp, M_LAGG);
if (oldmtu != -1)
(*ifp->if_ioctl)(ifp, SIOCSIFMTU,
(caddr_t)&ifr);
@@ -703,7 +704,7 @@ lagg_port_create(struct lagg_softc *sc, struct ifnet *ifp)
if (lagg_port_checkstacking(sc_ptr) >=
LAGG_MAX_STACKING) {
LAGG_LIST_UNLOCK();
- free(lp, M_DEVBUF);
+ free(lp, M_LAGG);
if (oldmtu != -1)
(*ifp->if_ioctl)(ifp, SIOCSIFMTU,
(caddr_t)&ifr);
@@ -751,7 +752,6 @@ lagg_port_create(struct lagg_softc *sc, struct ifnet *ifp)
* is predictable and `ifconfig laggN create ...` command
* will lead to the same result each time.
*/
- LAGG_RLOCK();
CK_SLIST_FOREACH(tlp, &sc->sc_ports, lp_entries) {
if (tlp->lp_ifp->if_index < ifp->if_index && (
CK_SLIST_NEXT(tlp, lp_entries) == NULL ||
@@ -759,7 +759,6 @@ lagg_port_create(struct lagg_softc *sc, struct ifnet *ifp)
ifp->if_index))
break;
}
- LAGG_RUNLOCK();
if (tlp != NULL)
CK_SLIST_INSERT_AFTER(tlp, lp, lp_entries);
else
@@ -814,7 +813,7 @@ lagg_port_destroy_cb(epoch_context_t ec)
ifp = lp->lp_ifp;
if_rele(ifp);
- free(lp, M_DEVBUF);
+ free(lp, M_LAGG);
}
static int
@@ -1537,14 +1536,17 @@ lagg_snd_tag_alloc(struct ifnet *ifp,
struct lagg_lb *lb;
uint32_t p;
+ LAGG_RLOCK();
switch (sc->sc_proto) {
case LAGG_PROTO_FAILOVER:
lp = lagg_link_active(sc, sc->sc_primary);
break;
case LAGG_PROTO_LOADBALANCE:
if ((sc->sc_opts & LAGG_OPT_USE_FLOWID) == 0 ||
- params->hdr.flowtype == M_HASHTYPE_NONE)
+ params->hdr.flowtype == M_HASHTYPE_NONE) {
+ LAGG_RUNLOCK();
return (EOPNOTSUPP);
+ }
p = params->hdr.flowid >> sc->flowid_shift;
p %= sc->sc_count;
lb = (struct lagg_lb *)sc->sc_psc;
@@ -1553,16 +1555,22 @@ lagg_snd_tag_alloc(struct ifnet *ifp,
break;
case LAGG_PROTO_LACP:
if ((sc->sc_opts & LAGG_OPT_USE_FLOWID) == 0 ||
- params->hdr.flowtype == M_HASHTYPE_NONE)
+ params->hdr.flowtype == M_HASHTYPE_NONE) {
+ LAGG_RUNLOCK();
return (EOPNOTSUPP);
+ }
lp = lacp_select_tx_port_by_hash(sc, params->hdr.flowid);
break;
default:
+ LAGG_RUNLOCK();
return (EOPNOTSUPP);
}
- if (lp == NULL)
+ if (lp == NULL) {
+ LAGG_RUNLOCK();
return (EOPNOTSUPP);
+ }
ifp = lp->lp_ifp;
+ LAGG_RUNLOCK();
if (ifp == NULL || ifp->if_snd_tag_alloc == NULL ||
(ifp->if_capenable & IFCAP_TXRTLMT) == 0)
return (EOPNOTSUPP);
@@ -1586,7 +1594,7 @@ lagg_setmulti(struct lagg_port *lp)
CK_STAILQ_FOREACH(ifma, &scifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_LINK)
continue;
- mc = malloc(sizeof(struct lagg_mc), M_DEVBUF, M_NOWAIT);
+ mc = malloc(sizeof(struct lagg_mc), M_LAGG, M_NOWAIT);
if (mc == NULL) {
IF_ADDR_WUNLOCK(scifp);
return (ENOMEM);
@@ -1617,7 +1625,7 @@ lagg_clrmulti(struct lagg_port *lp)
SLIST_REMOVE(&lp->lp_mc_head, mc, lagg_mc, mc_entries);
if (mc->mc_ifma && lp->lp_detaching == 0)
if_delmulti_ifma(mc->mc_ifma);
- free(mc, M_DEVBUF);
+ free(mc, M_LAGG);
}
return (0);
}
@@ -1846,12 +1854,20 @@ struct lagg_port *
lagg_link_active(struct lagg_softc *sc, struct lagg_port *lp)
{
struct lagg_port *lp_next, *rval = NULL;
- struct epoch_tracker net_et;
/*
* Search a port which reports an active link state.
*/
+#ifdef INVARIANTS
+ /*
+ * This is called with either LAGG_RLOCK() held or
+ * LAGG_XLOCK(sc) held.
+ */
+ if (!in_epoch(net_epoch_preempt))
+ LAGG_XLOCK_ASSERT(sc);
+#endif
+
if (lp == NULL)
goto search;
if (LAGG_PORTACTIVE(lp)) {
@@ -1864,15 +1880,12 @@ lagg_link_active(struct lagg_softc *sc, struct lagg_port *lp)
goto found;
}
- search:
- epoch_enter_preempt(net_epoch_preempt, &net_et);
+search:
CK_SLIST_FOREACH(lp_next, &sc->sc_ports, lp_entries) {
if (LAGG_PORTACTIVE(lp_next)) {
- epoch_exit_preempt(net_epoch_preempt, &net_et);
return (lp_next);
}
}
- epoch_exit_preempt(net_epoch_preempt, &net_et);
found:
return (rval);
}
@@ -1954,7 +1967,7 @@ lagg_bcast_start(struct lagg_softc *sc, struct mbuf *m)
struct lagg_port *lp, *last = NULL;
struct mbuf *m0;
- LAGG_RLOCK();
+ LAGG_RLOCK_ASSERT();
CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) {
if (!LAGG_PORTACTIVE(lp))
continue;
@@ -1975,7 +1988,6 @@ lagg_bcast_start(struct lagg_softc *sc, struct mbuf *m)
}
last = lp;
}
- LAGG_RUNLOCK();
if (last == NULL) {
m_freem(m);
@@ -2061,7 +2073,7 @@ lagg_lb_attach(struct lagg_softc *sc)
struct lagg_lb *lb;
LAGG_XLOCK_ASSERT(sc);
- lb = malloc(sizeof(struct lagg_lb), M_DEVBUF, M_WAITOK | M_ZERO);
+ lb = malloc(sizeof(struct lagg_lb), M_LAGG, M_WAITOK | M_ZERO);
lb->lb_key = m_ether_tcpip_hash_init();
sc->sc_psc = lb;
@@ -2076,7 +2088,7 @@ lagg_lb_detach(struct lagg_softc *sc)
lb = (struct lagg_lb *)sc->sc_psc;
if (lb != NULL)
- free(lb, M_DEVBUF);
+ free(lb, M_LAGG);
}
static int
@@ -2088,7 +2100,7 @@ lagg_lb_porttable(struct lagg_softc *sc, struct lagg_port *lp)
rv = 0;
bzero(&lb->lb_ports, sizeof(lb->lb_ports));
- LAGG_RLOCK();
+ LAGG_XLOCK_ASSERT(sc);
CK_SLIST_FOREACH(lp_next, &sc->sc_ports, lp_entries) {
if (lp_next == lp)
continue;
@@ -2101,7 +2113,6 @@ lagg_lb_porttable(struct lagg_softc *sc, struct lagg_port *lp)
sc->sc_ifname, lp_next->lp_ifp->if_xname, i);
lb->lb_ports[i++] = lp_next;
}
- LAGG_RUNLOCK();
return (rv);
}
diff --git a/freebsd/sys/net/if_stf.c b/freebsd/sys/net/if_stf.c
index 3ba9f8c0..7185fb8d 100644
--- a/freebsd/sys/net/if_stf.c
+++ b/freebsd/sys/net/if_stf.c
@@ -730,6 +730,7 @@ stf_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
}
ifp->if_flags |= IFF_UP;
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
break;
case SIOCADDMULTI:
diff --git a/freebsd/sys/net/if_tap.c b/freebsd/sys/net/if_tap.c
index a540a59a..4ca35b66 100644
--- a/freebsd/sys/net/if_tap.c
+++ b/freebsd/sys/net/if_tap.c
@@ -43,6 +43,7 @@
#include <sys/param.h>
#include <sys/conf.h>
+#include <sys/lock.h>
#include <sys/fcntl.h>
#include <sys/filio.h>
#include <sys/jail.h>
@@ -57,6 +58,7 @@
#include <sys/signalvar.h>
#include <sys/socket.h>
#include <sys/sockio.h>
+#include <sys/sx.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
#include <sys/ttycom.h>
@@ -165,6 +167,9 @@ MALLOC_DECLARE(M_TAP);
MALLOC_DEFINE(M_TAP, CDEV_NAME, "Ethernet tunnel interface");
SYSCTL_INT(_debug, OID_AUTO, if_tap_debug, CTLFLAG_RW, &tapdebug, 0, "");
+static struct sx tap_ioctl_sx;
+SX_SYSINIT(tap_ioctl_sx, &tap_ioctl_sx, "tap_ioctl");
+
SYSCTL_DECL(_net_link);
static SYSCTL_NODE(_net_link, OID_AUTO, tap, CTLFLAG_RW, 0,
"Ethernet tunnel software network interface");
@@ -177,6 +182,7 @@ SYSCTL_INT(_net_link_tap, OID_AUTO, devfs_cloning, CTLFLAG_RWTUN, &tapdclone, 0,
SYSCTL_INT(_net_link_tap, OID_AUTO, debug, CTLFLAG_RW, &tapdebug, 0, "");
DEV_MODULE(if_tap, tapmodevent, NULL);
+MODULE_VERSION(if_tap, 1);
static int
tap_clone_create(struct if_clone *ifc, int unit, caddr_t params)
@@ -219,11 +225,17 @@ tap_destroy(struct tap_softc *tp)
struct ifnet *ifp = tp->tap_ifp;
CURVNET_SET(ifp->if_vnet);
+
destroy_dev(tp->tap_dev);
seldrain(&tp->tap_rsel);
knlist_clear(&tp->tap_rsel.si_note, 0);
knlist_destroy(&tp->tap_rsel.si_note);
ether_ifdetach(ifp);
+
+ sx_xlock(&tap_ioctl_sx);
+ ifp->if_softc = NULL;
+ sx_xunlock(&tap_ioctl_sx);
+
if_free(ifp);
mtx_destroy(&tp->tap_mtx);
@@ -606,12 +618,18 @@ tapifinit(void *xtp)
static int
tapifioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
- struct tap_softc *tp = ifp->if_softc;
+ struct tap_softc *tp;
struct ifreq *ifr = (struct ifreq *)data;
struct ifstat *ifs = NULL;
struct ifmediareq *ifmr = NULL;
int dummy, error = 0;
+ sx_xlock(&tap_ioctl_sx);
+ tp = ifp->if_softc;
+ if (tp == NULL) {
+ error = ENXIO;
+ goto bad;
+ }
switch (cmd) {
case SIOCSIFFLAGS: /* XXX -- just like vmnet does */
case SIOCADDMULTI:
@@ -654,6 +672,8 @@ tapifioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
break;
}
+bad:
+ sx_xunlock(&tap_ioctl_sx);
return (error);
} /* tapifioctl */
diff --git a/freebsd/sys/net/if_tun.c b/freebsd/sys/net/if_tun.c
index ee5c78b0..9c11cbc2 100644
--- a/freebsd/sys/net/if_tun.c
+++ b/freebsd/sys/net/if_tun.c
@@ -22,6 +22,7 @@
#include <rtems/bsd/local/opt_inet6.h>
#include <sys/param.h>
+#include <sys/lock.h>
#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/systm.h>
@@ -32,6 +33,7 @@
#include <sys/fcntl.h>
#include <sys/filio.h>
#include <sys/sockio.h>
+#include <sys/sx.h>
#include <sys/ttycom.h>
#include <sys/poll.h>
#include <sys/selinfo.h>
@@ -81,17 +83,13 @@ struct tun_softc {
#define TUN_RWAIT 0x0040
#define TUN_ASYNC 0x0080
#define TUN_IFHEAD 0x0100
+#define TUN_DYING 0x0200
#define TUN_READY (TUN_OPEN | TUN_INITED)
- /*
- * XXXRW: tun_pid is used to exclusively lock /dev/tun. Is this
- * actually needed? Can we just return EBUSY if already open?
- * Problem is that this involved inherent races when a tun device
- * is handed off from one process to another, as opposed to just
- * being slightly stale informationally.
- */
+#ifndef __rtems__
pid_t tun_pid; /* owning pid */
+#endif /* __rtems__ */
struct ifnet *tun_ifp; /* the interface */
struct sigio *tun_sigio; /* information for async I/O */
struct selinfo tun_rsel; /* read select */
@@ -117,6 +115,9 @@ static struct clonedevs *tunclones;
static TAILQ_HEAD(,tun_softc) tunhead = TAILQ_HEAD_INITIALIZER(tunhead);
SYSCTL_INT(_debug, OID_AUTO, if_tun_debug, CTLFLAG_RW, &tundebug, 0, "");
+static struct sx tun_ioctl_sx;
+SX_SYSINIT(tun_ioctl_sx, &tun_ioctl_sx, "tun_ioctl");
+
SYSCTL_DECL(_net_link);
static SYSCTL_NODE(_net_link, OID_AUTO, tun, CTLFLAG_RW, 0,
"IP tunnel software network interface.");
@@ -274,15 +275,22 @@ tun_destroy(struct tun_softc *tp)
struct cdev *dev;
mtx_lock(&tp->tun_mtx);
+ tp->tun_flags |= TUN_DYING;
if ((tp->tun_flags & TUN_OPEN) != 0)
cv_wait_unlock(&tp->tun_cv, &tp->tun_mtx);
else
mtx_unlock(&tp->tun_mtx);
CURVNET_SET(TUN2IFP(tp)->if_vnet);
+
dev = tp->tun_dev;
bpfdetach(TUN2IFP(tp));
if_detach(TUN2IFP(tp));
+
+ sx_xlock(&tun_ioctl_sx);
+ TUN2IFP(tp)->if_softc = NULL;
+ sx_xunlock(&tun_ioctl_sx);
+
free_unr(tun_unrhdr, TUN2IFP(tp)->if_dunit);
if_free(TUN2IFP(tp));
destroy_dev(dev);
@@ -466,27 +474,15 @@ tunopen(struct cdev *dev, int flag, int mode, struct thread *td)
tp = dev->si_drv1;
}
- /*
- * XXXRW: This use of tun_pid is subject to error due to the
- * fact that a reference to the tunnel can live beyond the
- * death of the process that created it. Can we replace this
- * with a simple busy flag?
- */
mtx_lock(&tp->tun_mtx);
-#ifndef __rtems__
- if (tp->tun_pid != 0 && tp->tun_pid != td->td_proc->p_pid) {
-#else /* __rtems__ */
- if (tp->tun_pid != 0 && tp->tun_pid != BSD_DEFAULT_PID) {
-#endif /* __rtems__ */
+ if ((tp->tun_flags & (TUN_OPEN | TUN_DYING)) != 0) {
mtx_unlock(&tp->tun_mtx);
return (EBUSY);
}
+
#ifndef __rtems__
tp->tun_pid = td->td_proc->p_pid;
-#else /* __rtems__ */
- tp->tun_pid = BSD_DEFAULT_PID;
#endif /* __rtems__ */
-
tp->tun_flags |= TUN_OPEN;
ifp = TUN2IFP(tp);
if_link_state_change(ifp, LINK_STATE_UP);
@@ -510,8 +506,18 @@ tunclose(struct cdev *dev, int foo, int bar, struct thread *td)
ifp = TUN2IFP(tp);
mtx_lock(&tp->tun_mtx);
- tp->tun_flags &= ~TUN_OPEN;
- tp->tun_pid = 0;
+#ifndef __rtems__
+ /*
+ * Simply close the device if this isn't the controlling process. This
+ * may happen if, for instance, the tunnel has been handed off to
+ * another process. The original controller should be able to close it
+ * without putting us into an inconsistent state.
+ */
+ if (td->td_proc->p_pid != tp->tun_pid) {
+ mtx_unlock(&tp->tun_mtx);
+ return (0);
+ }
+#endif /* __rtems__ */
/*
* junk all pending output
@@ -550,6 +556,10 @@ tunclose(struct cdev *dev, int foo, int bar, struct thread *td)
selwakeuppri(&tp->tun_rsel, PZERO + 1);
KNOTE_LOCKED(&tp->tun_rsel.si_note, 0);
TUNDEBUG (ifp, "closed\n");
+ tp->tun_flags &= ~TUN_OPEN;
+#ifndef __rtems__
+ tp->tun_pid = 0;
+#endif /* __rtems__ */
cv_broadcast(&tp->tun_cv);
mtx_unlock(&tp->tun_mtx);
@@ -598,18 +608,26 @@ static int
tunifioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
struct ifreq *ifr = (struct ifreq *)data;
- struct tun_softc *tp = ifp->if_softc;
+ struct tun_softc *tp;
struct ifstat *ifs;
int error = 0;
+ sx_xlock(&tun_ioctl_sx);
+ tp = ifp->if_softc;
+ if (tp == NULL) {
+ error = ENXIO;
+ goto bad;
+ }
switch(cmd) {
case SIOCGIFSTATUS:
ifs = (struct ifstat *)data;
mtx_lock(&tp->tun_mtx);
+#ifndef __rtems__
if (tp->tun_pid)
snprintf(ifs->ascii, sizeof(ifs->ascii),
"\tOpened by PID %d\n", tp->tun_pid);
else
+#endif /* __rtems__ */
ifs->ascii[0] = '\0';
mtx_unlock(&tp->tun_mtx);
break;
@@ -628,6 +646,8 @@ tunifioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
default:
error = EINVAL;
}
+bad:
+ sx_xunlock(&tun_ioctl_sx);
return (error);
}
@@ -809,13 +829,11 @@ tunioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag,
}
break;
case TUNSIFPID:
- mtx_lock(&tp->tun_mtx);
#ifndef __rtems__
+ mtx_lock(&tp->tun_mtx);
tp->tun_pid = curthread->td_proc->p_pid;
-#else /* __rtems__ */
- tp->tun_pid = BSD_DEFAULT_PID;
-#endif /* __rtems__ */
mtx_unlock(&tp->tun_mtx);
+#endif /* __rtems__ */
break;
case FIONBIO:
break;
diff --git a/freebsd/sys/net/if_var.h b/freebsd/sys/net/if_var.h
index 6504837b..87551c4c 100644
--- a/freebsd/sys/net/if_var.h
+++ b/freebsd/sys/net/if_var.h
@@ -390,8 +390,7 @@ struct ifnet {
struct netdump_methods *if_netdump_methods;
#endif /* __rtems__ */
struct epoch_context if_epoch_ctx;
- struct epoch_tracker if_addr_et;
- struct epoch_tracker if_maddr_et;
+ void *if_unused[4];
#ifndef __rtems__
/*
diff --git a/freebsd/sys/net/iflib.h b/freebsd/sys/net/iflib.h
index f8524859..f718922e 100644
--- a/freebsd/sys/net/iflib.h
+++ b/freebsd/sys/net/iflib.h
@@ -248,7 +248,7 @@ struct if_shared_ctx {
/* fields necessary for probe */
pci_vendor_info_t *isc_vendor_info;
- char *isc_driver_version;
+ const char *isc_driver_version;
/* optional function to transform the read values to match the table*/
void (*isc_parse_devinfo) (uint16_t *device_id, uint16_t *subvendor_id,
uint16_t *subdevice_id, uint16_t *rev_id);
@@ -381,6 +381,8 @@ void iflib_set_mac(if_ctx_t ctx, uint8_t mac[ETHER_ADDR_LEN]);
void iflib_request_reset(if_ctx_t ctx);
uint8_t iflib_in_detach(if_ctx_t ctx);
+uint32_t iflib_get_rx_mbuf_sz(if_ctx_t ctx);
+
/*
* If the driver can plug cleanly in to newbus use these
*/
diff --git a/freebsd/sys/net/pfvar.h b/freebsd/sys/net/pfvar.h
index 22159bd9..248c1938 100644
--- a/freebsd/sys/net/pfvar.h
+++ b/freebsd/sys/net/pfvar.h
@@ -1021,6 +1021,17 @@ struct pfr_tstats {
int pfrts_cnt;
int pfrts_refcnt[PFR_REFCNT_MAX];
};
+
+struct pfr_ktstats {
+ struct pfr_table pfrts_t;
+ counter_u64_t pfrkts_packets[PFR_DIR_MAX][PFR_OP_TABLE_MAX];
+ counter_u64_t pfrkts_bytes[PFR_DIR_MAX][PFR_OP_TABLE_MAX];
+ counter_u64_t pfrkts_match;
+ counter_u64_t pfrkts_nomatch;
+ long pfrkts_tzero;
+ int pfrkts_cnt;
+ int pfrkts_refcnt[PFR_REFCNT_MAX];
+};
#define pfrts_name pfrts_t.pfrt_name
#define pfrts_flags pfrts_t.pfrt_flags
@@ -1034,8 +1045,9 @@ union sockaddr_union {
#endif /* _SOCKADDR_UNION_DEFINED */
struct pfr_kcounters {
- u_int64_t pfrkc_packets[PFR_DIR_MAX][PFR_OP_ADDR_MAX];
- u_int64_t pfrkc_bytes[PFR_DIR_MAX][PFR_OP_ADDR_MAX];
+ counter_u64_t pfrkc_packets[PFR_DIR_MAX][PFR_OP_ADDR_MAX];
+ counter_u64_t pfrkc_bytes[PFR_DIR_MAX][PFR_OP_ADDR_MAX];
+ long pfrkc_tzero;
};
SLIST_HEAD(pfr_kentryworkq, pfr_kentry);
@@ -1043,8 +1055,7 @@ struct pfr_kentry {
struct radix_node pfrke_node[2];
union sockaddr_union pfrke_sa;
SLIST_ENTRY(pfr_kentry) pfrke_workq;
- struct pfr_kcounters *pfrke_counters;
- long pfrke_tzero;
+ struct pfr_kcounters pfrke_counters;
u_int8_t pfrke_af;
u_int8_t pfrke_net;
u_int8_t pfrke_not;
@@ -1054,7 +1065,7 @@ struct pfr_kentry {
SLIST_HEAD(pfr_ktableworkq, pfr_ktable);
RB_HEAD(pfr_ktablehead, pfr_ktable);
struct pfr_ktable {
- struct pfr_tstats pfrkt_ts;
+ struct pfr_ktstats pfrkt_kts;
RB_ENTRY(pfr_ktable) pfrkt_tree;
SLIST_ENTRY(pfr_ktable) pfrkt_workq;
struct radix_node_head *pfrkt_ip4;
@@ -1065,18 +1076,18 @@ struct pfr_ktable {
long pfrkt_larg;
int pfrkt_nflags;
};
-#define pfrkt_t pfrkt_ts.pfrts_t
+#define pfrkt_t pfrkt_kts.pfrts_t
#define pfrkt_name pfrkt_t.pfrt_name
#define pfrkt_anchor pfrkt_t.pfrt_anchor
#define pfrkt_ruleset pfrkt_t.pfrt_ruleset
#define pfrkt_flags pfrkt_t.pfrt_flags
-#define pfrkt_cnt pfrkt_ts.pfrts_cnt
-#define pfrkt_refcnt pfrkt_ts.pfrts_refcnt
-#define pfrkt_packets pfrkt_ts.pfrts_packets
-#define pfrkt_bytes pfrkt_ts.pfrts_bytes
-#define pfrkt_match pfrkt_ts.pfrts_match
-#define pfrkt_nomatch pfrkt_ts.pfrts_nomatch
-#define pfrkt_tzero pfrkt_ts.pfrts_tzero
+#define pfrkt_cnt pfrkt_kts.pfrkts_cnt
+#define pfrkt_refcnt pfrkt_kts.pfrkts_refcnt
+#define pfrkt_packets pfrkt_kts.pfrkts_packets
+#define pfrkt_bytes pfrkt_kts.pfrkts_bytes
+#define pfrkt_match pfrkt_kts.pfrkts_match
+#define pfrkt_nomatch pfrkt_kts.pfrkts_nomatch
+#define pfrkt_tzero pfrkt_kts.pfrkts_tzero
/* keep synced with pfi_kif, used in RB_FIND */
struct pfi_kif_cmp {
diff --git a/freebsd/sys/net/rtsock.c b/freebsd/sys/net/rtsock.c
index e1b87095..35656e48 100644
--- a/freebsd/sys/net/rtsock.c
+++ b/freebsd/sys/net/rtsock.c
@@ -627,6 +627,8 @@ route_output(struct mbuf *m, struct socket *so, ...)
if (rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info))
senderr(EINVAL);
+ if (rtm->rtm_flags & RTF_RNH_LOCKED)
+ senderr(EINVAL);
info.rti_flags = rtm->rtm_flags;
if (info.rti_info[RTAX_DST] == NULL ||
info.rti_info[RTAX_DST]->sa_family >= AF_MAX ||
diff --git a/freebsd/sys/net80211/ieee80211_ht.c b/freebsd/sys/net80211/ieee80211_ht.c
index c5ce444b..da294488 100644
--- a/freebsd/sys/net80211/ieee80211_ht.c
+++ b/freebsd/sys/net80211/ieee80211_ht.c
@@ -1729,7 +1729,7 @@ ieee80211_ht_updateparams(struct ieee80211_node *ni,
const struct ieee80211_ie_htinfo *htinfo;
ieee80211_parse_htcap(ni, htcapie);
- if (vap->iv_htcaps & IEEE80211_HTCAP_SMPS)
+ if (vap->iv_htcaps & IEEE80211_HTC_SMPS)
htcap_update_mimo_ps(ni);
htcap_update_shortgi(ni);
htcap_update_ldpc(ni);
@@ -1882,7 +1882,7 @@ ieee80211_ht_updatehtcap(struct ieee80211_node *ni, const uint8_t *htcapie)
struct ieee80211vap *vap = ni->ni_vap;
ieee80211_parse_htcap(ni, htcapie);
- if (vap->iv_htcaps & IEEE80211_HTCAP_SMPS)
+ if (vap->iv_htcaps & IEEE80211_HTC_SMPS)
htcap_update_mimo_ps(ni);
htcap_update_shortgi(ni);
htcap_update_ldpc(ni);
diff --git a/freebsd/sys/netinet/cc/cc_newreno.c b/freebsd/sys/netinet/cc/cc_newreno.c
index b1307c92..1ab85042 100644
--- a/freebsd/sys/netinet/cc/cc_newreno.c
+++ b/freebsd/sys/netinet/cc/cc_newreno.c
@@ -301,7 +301,12 @@ newreno_post_recovery(struct cc_var *ccv)
pipe = CCV(ccv, snd_max) - ccv->curack;
if (pipe < CCV(ccv, snd_ssthresh))
- CCV(ccv, snd_cwnd) = pipe + CCV(ccv, t_maxseg);
+ /*
+ * Ensure that cwnd does not collapse to 1 MSS under
+ * adverse conditons. Implements RFC6582
+ */
+ CCV(ccv, snd_cwnd) = max(pipe, CCV(ccv, t_maxseg)) +
+ CCV(ccv, t_maxseg);
else
CCV(ccv, snd_cwnd) = CCV(ccv, snd_ssthresh);
}
diff --git a/freebsd/sys/netinet/if_ether.c b/freebsd/sys/netinet/if_ether.c
index 5539e973..a71cb7a5 100644
--- a/freebsd/sys/netinet/if_ether.c
+++ b/freebsd/sys/netinet/if_ether.c
@@ -435,10 +435,10 @@ arprequest(struct ifnet *ifp, const struct in_addr *sip,
/*
* Resolve an IP address into an ethernet address - heavy version.
* Used internally by arpresolve().
- * We have already checked than we can't use existing lle without
- * modification so we have to acquire LLE_EXCLUSIVE lle lock.
+ * We have already checked that we can't use an existing lle without
+ * modification so we have to acquire an LLE_EXCLUSIVE lle lock.
*
- * On success, desten and flags are filled in and the function returns 0;
+ * On success, desten and pflags are filled in and the function returns 0;
* If the packet must be held pending resolution, we return EWOULDBLOCK
* On other errors, we return the corresponding error code.
* Note that m_freem() handles NULL.
diff --git a/freebsd/sys/netinet/in.c b/freebsd/sys/netinet/in.c
index ae32c8d9..f001faa5 100644
--- a/freebsd/sys/netinet/in.c
+++ b/freebsd/sys/netinet/in.c
@@ -192,15 +192,10 @@ int
in_canforward(struct in_addr in)
{
u_long i = ntohl(in.s_addr);
- u_long net;
- if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i) || IN_LINKLOCAL(i))
+ if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i) || IN_LINKLOCAL(i) ||
+ IN_ZERONET(i) || IN_LOOPBACK(i))
return (0);
- if (IN_CLASSA(i)) {
- net = i & IN_CLASSA_NET;
- if (net == 0 || net == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
- return (0);
- }
return (1);
}
diff --git a/freebsd/sys/netinet/in_mcast.c b/freebsd/sys/netinet/in_mcast.c
index 3b1d57f8..b989944c 100644
--- a/freebsd/sys/netinet/in_mcast.c
+++ b/freebsd/sys/netinet/in_mcast.c
@@ -2048,41 +2048,50 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt)
ssa->ss.ss_family = AF_UNSPEC;
switch (sopt->sopt_name) {
- case IP_ADD_MEMBERSHIP:
- case IP_ADD_SOURCE_MEMBERSHIP: {
- struct ip_mreq_source mreqs;
+ case IP_ADD_MEMBERSHIP: {
+ struct ip_mreqn mreqn;
- if (sopt->sopt_name == IP_ADD_MEMBERSHIP) {
- error = sooptcopyin(sopt, &mreqs,
- sizeof(struct ip_mreq),
- sizeof(struct ip_mreq));
- /*
- * Do argument switcharoo from ip_mreq into
- * ip_mreq_source to avoid using two instances.
- */
- mreqs.imr_interface = mreqs.imr_sourceaddr;
- mreqs.imr_sourceaddr.s_addr = INADDR_ANY;
- } else if (sopt->sopt_name == IP_ADD_SOURCE_MEMBERSHIP) {
- error = sooptcopyin(sopt, &mreqs,
- sizeof(struct ip_mreq_source),
- sizeof(struct ip_mreq_source));
- }
+ if (sopt->sopt_valsize == sizeof(struct ip_mreqn))
+ error = sooptcopyin(sopt, &mreqn,
+ sizeof(struct ip_mreqn), sizeof(struct ip_mreqn));
+ else
+ error = sooptcopyin(sopt, &mreqn,
+ sizeof(struct ip_mreq), sizeof(struct ip_mreq));
if (error)
return (error);
gsa->sin.sin_family = AF_INET;
gsa->sin.sin_len = sizeof(struct sockaddr_in);
- gsa->sin.sin_addr = mreqs.imr_multiaddr;
+ gsa->sin.sin_addr = mreqn.imr_multiaddr;
+ if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr)))
+ return (EINVAL);
- if (sopt->sopt_name == IP_ADD_SOURCE_MEMBERSHIP) {
- ssa->sin.sin_family = AF_INET;
- ssa->sin.sin_len = sizeof(struct sockaddr_in);
- ssa->sin.sin_addr = mreqs.imr_sourceaddr;
- }
+ if (sopt->sopt_valsize == sizeof(struct ip_mreqn) &&
+ mreqn.imr_ifindex != 0)
+ ifp = ifnet_byindex(mreqn.imr_ifindex);
+ else
+ ifp = inp_lookup_mcast_ifp(inp, &gsa->sin,
+ mreqn.imr_address);
+ break;
+ }
+ case IP_ADD_SOURCE_MEMBERSHIP: {
+ struct ip_mreq_source mreqs;
+ error = sooptcopyin(sopt, &mreqs, sizeof(struct ip_mreq_source),
+ sizeof(struct ip_mreq_source));
+ if (error)
+ return (error);
+
+ gsa->sin.sin_family = ssa->sin.sin_family = AF_INET;
+ gsa->sin.sin_len = ssa->sin.sin_len =
+ sizeof(struct sockaddr_in);
+
+ gsa->sin.sin_addr = mreqs.imr_multiaddr;
if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr)))
return (EINVAL);
+ ssa->sin.sin_addr = mreqs.imr_sourceaddr;
+
ifp = inp_lookup_mcast_ifp(inp, &gsa->sin,
mreqs.imr_interface);
CTR3(KTR_IGMPV3, "%s: imr_interface = 0x%08x, ifp = %p",
@@ -2546,10 +2555,14 @@ out_in_multi_locked:
if (is_final) {
/* Remove the gap in the membership and filter array. */
+ KASSERT(RB_EMPTY(&imf->imf_sources),
+ ("%s: imf_sources not empty", __func__));
for (++idx; idx < imo->imo_num_memberships; ++idx) {
- imo->imo_membership[idx-1] = imo->imo_membership[idx];
- imo->imo_mfilters[idx-1] = imo->imo_mfilters[idx];
+ imo->imo_membership[idx - 1] = imo->imo_membership[idx];
+ imo->imo_mfilters[idx - 1] = imo->imo_mfilters[idx];
}
+ imf_init(&imo->imo_mfilters[idx - 1], MCAST_UNDEFINED,
+ MCAST_EXCLUDE);
imo->imo_num_memberships--;
}
@@ -3052,7 +3065,14 @@ sysctl_ip_mcast_filters(SYSCTL_HANDLER_ARGS)
#if defined(KTR) && (KTR_COMPILE & KTR_IGMPV3)
-static const char *inm_modestrs[] = { "un", "in", "ex" };
+static const char *inm_modestrs[] = {
+ [MCAST_UNDEFINED] = "un",
+ [MCAST_INCLUDE] = "in",
+ [MCAST_EXCLUDE] = "ex",
+};
+_Static_assert(MCAST_UNDEFINED == 0 &&
+ MCAST_EXCLUDE + 1 == nitems(inm_modestrs),
+ "inm_modestrs: no longer matches #defines");
static const char *
inm_mode_str(const int mode)
@@ -3064,16 +3084,20 @@ inm_mode_str(const int mode)
}
static const char *inm_statestrs[] = {
- "not-member",
- "silent",
- "idle",
- "lazy",
- "sleeping",
- "awakening",
- "query-pending",
- "sg-query-pending",
- "leaving"
+ [IGMP_NOT_MEMBER] = "not-member",
+ [IGMP_SILENT_MEMBER] = "silent",
+ [IGMP_REPORTING_MEMBER] = "reporting",
+ [IGMP_IDLE_MEMBER] = "idle",
+ [IGMP_LAZY_MEMBER] = "lazy",
+ [IGMP_SLEEPING_MEMBER] = "sleeping",
+ [IGMP_AWAKENING_MEMBER] = "awakening",
+ [IGMP_G_QUERY_PENDING_MEMBER] = "query-pending",
+ [IGMP_SG_QUERY_PENDING_MEMBER] = "sg-query-pending",
+ [IGMP_LEAVING_MEMBER] = "leaving",
};
+_Static_assert(IGMP_NOT_MEMBER == 0 &&
+ IGMP_LEAVING_MEMBER + 1 == nitems(inm_statestrs),
+ "inm_statetrs: no longer matches #defines");
static const char *
inm_state_str(const int state)
diff --git a/freebsd/sys/netinet/in_pcb.c b/freebsd/sys/netinet/in_pcb.c
index 0bebb9ea..abcee41b 100644
--- a/freebsd/sys/netinet/in_pcb.c
+++ b/freebsd/sys/netinet/in_pcb.c
@@ -3410,16 +3410,11 @@ in_pcboutput_txrtlmt(struct inpcb *inp, struct ifnet *ifp, struct mbuf *mb)
void
in_pcboutput_eagain(struct inpcb *inp)
{
- struct socket *socket;
bool did_upgrade;
if (inp == NULL)
return;
- socket = inp->inp_socket;
- if (socket == NULL)
- return;
-
if (inp->inp_snd_tag == NULL)
return;
diff --git a/freebsd/sys/netinet/ip_fw.h b/freebsd/sys/netinet/ip_fw.h
index 41351215..de0cc29d 100644
--- a/freebsd/sys/netinet/ip_fw.h
+++ b/freebsd/sys/netinet/ip_fw.h
@@ -134,6 +134,13 @@ typedef struct _ip_fw3_opheader {
#define IP_FW_NPTV6_STATS 154 /* Get NPTv6 instance statistics */
#define IP_FW_NPTV6_RESET_STATS 155 /* Reset NPTv6 instance statistics */
+#define IP_FW_NAT64CLAT_CREATE 160 /* Create clat NAT64 instance */
+#define IP_FW_NAT64CLAT_DESTROY 161 /* Destroy clat NAT64 instance */
+#define IP_FW_NAT64CLAT_CONFIG 162 /* Modify clat NAT64 instance */
+#define IP_FW_NAT64CLAT_LIST 163 /* List clat NAT64 instances */
+#define IP_FW_NAT64CLAT_STATS 164 /* Get NAT64CLAT instance statistics */
+#define IP_FW_NAT64CLAT_RESET_STATS 165 /* Reset NAT64CLAT instance statistics */
+
/*
* The kernel representation of ipfw rules is made of a list of
* 'instructions' (for all practical purposes equivalent to BPF
diff --git a/freebsd/sys/netinet/ip_gre.c b/freebsd/sys/netinet/ip_gre.c
index 1758bfff..5a024e16 100644
--- a/freebsd/sys/netinet/ip_gre.c
+++ b/freebsd/sys/netinet/ip_gre.c
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <sys/jail.h>
#include <sys/systm.h>
#include <sys/socket.h>
+#include <sys/socketvar.h>
#include <sys/sockio.h>
#include <sys/mbuf.h>
#include <sys/errno.h>
@@ -60,15 +61,19 @@ __FBSDID("$FreeBSD$");
#include <netinet/in.h>
#include <netinet/in_var.h>
+#include <netinet/in_pcb.h>
#include <netinet/ip.h>
#include <netinet/ip_encap.h>
#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
#ifdef INET6
#include <netinet/ip6.h>
#endif
#include <net/if_gre.h>
+#include <machine/in_cksum.h>
#define GRE_TTL 30
VNET_DEFINE(int, ip_gre_ttl) = GRE_TTL;
@@ -76,14 +81,22 @@ VNET_DEFINE(int, ip_gre_ttl) = GRE_TTL;
SYSCTL_INT(_net_inet_ip, OID_AUTO, grettl, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(ip_gre_ttl), 0, "Default TTL value for encapsulated packets");
+struct in_gre_socket {
+ struct gre_socket base;
+ in_addr_t addr;
+};
+VNET_DEFINE_STATIC(struct gre_sockets *, ipv4_sockets) = NULL;
VNET_DEFINE_STATIC(struct gre_list *, ipv4_hashtbl) = NULL;
VNET_DEFINE_STATIC(struct gre_list *, ipv4_srchashtbl) = NULL;
+#define V_ipv4_sockets VNET(ipv4_sockets)
#define V_ipv4_hashtbl VNET(ipv4_hashtbl)
#define V_ipv4_srchashtbl VNET(ipv4_srchashtbl)
#define GRE_HASH(src, dst) (V_ipv4_hashtbl[\
in_gre_hashval((src), (dst)) & (GRE_HASH_SIZE - 1)])
#define GRE_SRCHASH(src) (V_ipv4_srchashtbl[\
fnv_32_buf(&(src), sizeof(src), FNV1_32_INIT) & (GRE_HASH_SIZE - 1)])
+#define GRE_SOCKHASH(src) (V_ipv4_sockets[\
+ fnv_32_buf(&(src), sizeof(src), FNV1_32_INIT) & (GRE_HASH_SIZE - 1)])
#define GRE_HASH_SC(sc) GRE_HASH((sc)->gre_oip.ip_src.s_addr,\
(sc)->gre_oip.ip_dst.s_addr)
@@ -96,17 +109,43 @@ in_gre_hashval(in_addr_t src, in_addr_t dst)
return (fnv_32_buf(&dst, sizeof(dst), ret));
}
+static struct gre_socket*
+in_gre_lookup_socket(in_addr_t addr)
+{
+ struct gre_socket *gs;
+ struct in_gre_socket *s;
+
+ CK_LIST_FOREACH(gs, &GRE_SOCKHASH(addr), chain) {
+ s = __containerof(gs, struct in_gre_socket, base);
+ if (s->addr == addr)
+ break;
+ }
+ return (gs);
+}
+
static int
-in_gre_checkdup(const struct gre_softc *sc, in_addr_t src, in_addr_t dst)
+in_gre_checkdup(const struct gre_softc *sc, in_addr_t src, in_addr_t dst,
+ uint32_t opts)
{
+ struct gre_list *head;
struct gre_softc *tmp;
+ struct gre_socket *gs;
if (sc->gre_family == AF_INET &&
sc->gre_oip.ip_src.s_addr == src &&
- sc->gre_oip.ip_dst.s_addr == dst)
+ sc->gre_oip.ip_dst.s_addr == dst &&
+ (sc->gre_options & GRE_UDPENCAP) == (opts & GRE_UDPENCAP))
return (EEXIST);
- CK_LIST_FOREACH(tmp, &GRE_HASH(src, dst), chain) {
+ if (opts & GRE_UDPENCAP) {
+ gs = in_gre_lookup_socket(src);
+ if (gs == NULL)
+ return (0);
+ head = &gs->list;
+ } else
+ head = &GRE_HASH(src, dst);
+
+ CK_LIST_FOREACH(tmp, head, chain) {
if (tmp == sc)
continue;
if (tmp->gre_oip.ip_src.s_addr == src &&
@@ -183,35 +222,228 @@ in_gre_srcaddr(void *arg __unused, const struct sockaddr *sa,
}
static void
+in_gre_udp_input(struct mbuf *m, int off, struct inpcb *inp,
+ const struct sockaddr *sa, void *ctx)
+{
+ struct epoch_tracker et;
+ struct gre_socket *gs;
+ struct gre_softc *sc;
+ in_addr_t dst;
+
+ NET_EPOCH_ENTER_ET(et);
+ /*
+ * udp_append() holds reference to inp, it is safe to check
+ * inp_flags2 without INP_RLOCK().
+ * If socket was closed before we have entered NET_EPOCH section,
+ * INP_FREED flag should be set. Otherwise it should be safe to
+ * make access to ctx data, because gre_so will be freed by
+ * gre_sofree() via epoch_call().
+ */
+ if (__predict_false(inp->inp_flags2 & INP_FREED)) {
+ NET_EPOCH_EXIT_ET(et);
+ m_freem(m);
+ return;
+ }
+
+ gs = (struct gre_socket *)ctx;
+ dst = ((const struct sockaddr_in *)sa)->sin_addr.s_addr;
+ CK_LIST_FOREACH(sc, &gs->list, chain) {
+ if (sc->gre_oip.ip_dst.s_addr == dst)
+ break;
+ }
+ if (sc != NULL && (GRE2IFP(sc)->if_flags & IFF_UP) != 0){
+ gre_input(m, off + sizeof(struct udphdr), IPPROTO_UDP, sc);
+ NET_EPOCH_EXIT_ET(et);
+ return;
+ }
+ m_freem(m);
+ NET_EPOCH_EXIT_ET(et);
+}
+
+static int
+in_gre_setup_socket(struct gre_softc *sc)
+{
+ struct sockopt sopt;
+ struct sockaddr_in sin;
+ struct in_gre_socket *s;
+ struct gre_socket *gs;
+ in_addr_t addr;
+ int error, value;
+
+ /*
+ * NOTE: we are protected with gre_ioctl_sx lock.
+ *
+ * First check that socket is already configured.
+ * If so, check that source addres was not changed.
+ * If address is different, check that there are no other tunnels
+ * and close socket.
+ */
+ addr = sc->gre_oip.ip_src.s_addr;
+ gs = sc->gre_so;
+ if (gs != NULL) {
+ s = __containerof(gs, struct in_gre_socket, base);
+ if (s->addr != addr) {
+ if (CK_LIST_EMPTY(&gs->list)) {
+ CK_LIST_REMOVE(gs, chain);
+ soclose(gs->so);
+ epoch_call(net_epoch_preempt, &gs->epoch_ctx,
+ gre_sofree);
+ }
+ gs = sc->gre_so = NULL;
+ }
+ }
+
+ if (gs == NULL) {
+ /*
+ * Check that socket for given address is already
+ * configured.
+ */
+ gs = in_gre_lookup_socket(addr);
+ if (gs == NULL) {
+ s = malloc(sizeof(*s), M_GRE, M_WAITOK | M_ZERO);
+ s->addr = addr;
+ gs = &s->base;
+
+ error = socreate(sc->gre_family, &gs->so,
+ SOCK_DGRAM, IPPROTO_UDP, curthread->td_ucred,
+ curthread);
+ if (error != 0) {
+ if_printf(GRE2IFP(sc),
+ "cannot create socket: %d\n", error);
+ free(s, M_GRE);
+ return (error);
+ }
+
+ error = udp_set_kernel_tunneling(gs->so,
+ in_gre_udp_input, NULL, gs);
+ if (error != 0) {
+ if_printf(GRE2IFP(sc),
+ "cannot set UDP tunneling: %d\n", error);
+ goto fail;
+ }
+
+ memset(&sopt, 0, sizeof(sopt));
+ sopt.sopt_dir = SOPT_SET;
+ sopt.sopt_level = IPPROTO_IP;
+ sopt.sopt_name = IP_BINDANY;
+ sopt.sopt_val = &value;
+ sopt.sopt_valsize = sizeof(value);
+ value = 1;
+ error = sosetopt(gs->so, &sopt);
+ if (error != 0) {
+ if_printf(GRE2IFP(sc),
+ "cannot set IP_BINDANY opt: %d\n", error);
+ goto fail;
+ }
+
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_len = sizeof(sin);
+ sin.sin_addr.s_addr = addr;
+ sin.sin_port = htons(GRE_UDPPORT);
+ error = sobind(gs->so, (struct sockaddr *)&sin,
+ curthread);
+ if (error != 0) {
+ if_printf(GRE2IFP(sc),
+ "cannot bind socket: %d\n", error);
+ goto fail;
+ }
+ /* Add socket to the chain */
+ CK_LIST_INSERT_HEAD(&GRE_SOCKHASH(addr), gs, chain);
+ }
+ }
+
+ /* Add softc to the socket's list */
+ CK_LIST_INSERT_HEAD(&gs->list, sc, chain);
+ sc->gre_so = gs;
+ return (0);
+fail:
+ soclose(gs->so);
+ free(s, M_GRE);
+ return (error);
+}
+
+static int
in_gre_attach(struct gre_softc *sc)
{
+ struct grehdr *gh;
+ int error;
- sc->gre_hlen = sizeof(struct greip);
+ if (sc->gre_options & GRE_UDPENCAP) {
+ sc->gre_csumflags = CSUM_UDP;
+ sc->gre_hlen = sizeof(struct greudp);
+ sc->gre_oip.ip_p = IPPROTO_UDP;
+ gh = &sc->gre_udphdr->gi_gre;
+ gre_update_udphdr(sc, &sc->gre_udp,
+ in_pseudo(sc->gre_oip.ip_src.s_addr,
+ sc->gre_oip.ip_dst.s_addr, 0));
+ } else {
+ sc->gre_hlen = sizeof(struct greip);
+ sc->gre_oip.ip_p = IPPROTO_GRE;
+ gh = &sc->gre_iphdr->gi_gre;
+ }
sc->gre_oip.ip_v = IPVERSION;
sc->gre_oip.ip_hl = sizeof(struct ip) >> 2;
- sc->gre_oip.ip_p = IPPROTO_GRE;
- gre_updatehdr(sc, &sc->gre_gihdr->gi_gre);
- CK_LIST_INSERT_HEAD(&GRE_HASH_SC(sc), sc, chain);
+ gre_update_hdr(sc, gh);
+
+ /*
+ * If we return error, this means that sc is not linked,
+ * and caller should reset gre_family and free(sc->gre_hdr).
+ */
+ if (sc->gre_options & GRE_UDPENCAP) {
+ error = in_gre_setup_socket(sc);
+ if (error != 0)
+ return (error);
+ } else
+ CK_LIST_INSERT_HEAD(&GRE_HASH_SC(sc), sc, chain);
CK_LIST_INSERT_HEAD(&GRE_SRCHASH(sc->gre_oip.ip_src.s_addr),
sc, srchash);
+
+ /* Set IFF_DRV_RUNNING if interface is ready */
+ in_gre_set_running(sc);
+ return (0);
}
-void
+int
in_gre_setopts(struct gre_softc *sc, u_long cmd, uint32_t value)
{
-
- MPASS(cmd == GRESKEY || cmd == GRESOPTS);
+ int error;
/* NOTE: we are protected with gre_ioctl_sx lock */
+ MPASS(cmd == GRESKEY || cmd == GRESOPTS || cmd == GRESPORT);
MPASS(sc->gre_family == AF_INET);
+
+ /*
+ * If we are going to change encapsulation protocol, do check
+ * for duplicate tunnels. Return EEXIST here to do not confuse
+ * user.
+ */
+ if (cmd == GRESOPTS &&
+ (sc->gre_options & GRE_UDPENCAP) != (value & GRE_UDPENCAP) &&
+ in_gre_checkdup(sc, sc->gre_oip.ip_src.s_addr,
+ sc->gre_oip.ip_dst.s_addr, value) == EADDRNOTAVAIL)
+ return (EEXIST);
+
CK_LIST_REMOVE(sc, chain);
CK_LIST_REMOVE(sc, srchash);
GRE_WAIT();
- if (cmd == GRESKEY)
+ switch (cmd) {
+ case GRESKEY:
sc->gre_key = value;
- else
+ break;
+ case GRESOPTS:
sc->gre_options = value;
- in_gre_attach(sc);
+ break;
+ case GRESPORT:
+ sc->gre_port = value;
+ break;
+ }
+ error = in_gre_attach(sc);
+ if (error != 0) {
+ sc->gre_family = 0;
+ free(sc->gre_hdr, M_GRE);
+ }
+ return (error);
}
int
@@ -243,9 +475,10 @@ in_gre_ioctl(struct gre_softc *sc, u_long cmd, caddr_t data)
if (V_ipv4_hashtbl == NULL) {
V_ipv4_hashtbl = gre_hashinit();
V_ipv4_srchashtbl = gre_hashinit();
+ V_ipv4_sockets = (struct gre_sockets *)gre_hashinit();
}
error = in_gre_checkdup(sc, src->sin_addr.s_addr,
- dst->sin_addr.s_addr);
+ dst->sin_addr.s_addr, sc->gre_options);
if (error == EADDRNOTAVAIL)
break;
if (error == EEXIST) {
@@ -253,7 +486,7 @@ in_gre_ioctl(struct gre_softc *sc, u_long cmd, caddr_t data)
error = 0;
break;
}
- ip = malloc(sizeof(struct greip) + 3 * sizeof(uint32_t),
+ ip = malloc(sizeof(struct greudp) + 3 * sizeof(uint32_t),
M_GRE, M_WAITOK | M_ZERO);
ip->ip_src.s_addr = src->sin_addr.s_addr;
ip->ip_dst.s_addr = dst->sin_addr.s_addr;
@@ -269,8 +502,11 @@ in_gre_ioctl(struct gre_softc *sc, u_long cmd, caddr_t data)
sc->gre_hdr = ip;
sc->gre_oseq = 0;
sc->gre_iseq = UINT32_MAX;
- in_gre_attach(sc);
- in_gre_set_running(sc);
+ error = in_gre_attach(sc);
+ if (error != 0) {
+ sc->gre_family = 0;
+ free(sc->gre_hdr, M_GRE);
+ }
break;
case SIOCGIFPSRCADDR:
case SIOCGIFPDSTADDR:
@@ -356,5 +592,6 @@ in_gre_uninit(void)
V_ipv4_hashtbl = NULL;
GRE_WAIT();
gre_hashdestroy(V_ipv4_srchashtbl);
+ gre_hashdestroy((struct gre_list *)V_ipv4_sockets);
}
}
diff --git a/freebsd/sys/netinet/ip_icmp.c b/freebsd/sys/netinet/ip_icmp.c
index b7f0d3b1..970c680a 100644
--- a/freebsd/sys/netinet/ip_icmp.c
+++ b/freebsd/sys/netinet/ip_icmp.c
@@ -156,7 +156,7 @@ SYSCTL_INT(_net_inet_icmp, OID_AUTO, bmcastecho, CTLFLAG_VNET | CTLFLAG_RW,
VNET_DEFINE_STATIC(int, icmptstamprepl) = 1;
#define V_icmptstamprepl VNET(icmptstamprepl)
-SYSCTL_INT(_net_inet_icmp, OID_AUTO, tstamprepl, CTLFLAG_RW,
+SYSCTL_INT(_net_inet_icmp, OID_AUTO, tstamprepl, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(icmptstamprepl), 0,
"Respond to ICMP Timestamp packets");
diff --git a/freebsd/sys/netinet/ip_input.c b/freebsd/sys/netinet/ip_input.c
index 136a774f..191b7867 100644
--- a/freebsd/sys/netinet/ip_input.c
+++ b/freebsd/sys/netinet/ip_input.c
@@ -503,10 +503,10 @@ ip_input(struct mbuf *m)
IP_PROBE(receive, NULL, NULL, ip, m->m_pkthdr.rcvif, ip, NULL);
- /* 127/8 must not appear on wire - RFC1122 */
+ /* IN_LOOPBACK must not appear on the wire - RFC1122 */
ifp = m->m_pkthdr.rcvif;
- if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET ||
- (ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) {
+ if (IN_LOOPBACK(ntohl(ip->ip_dst.s_addr)) ||
+ IN_LOOPBACK(ntohl(ip->ip_src.s_addr))) {
if ((ifp->if_flags & IFF_LOOPBACK) == 0) {
IPSTAT_INC(ips_badaddr);
goto bad;
diff --git a/freebsd/sys/netinet/ip_output.c b/freebsd/sys/netinet/ip_output.c
index bf83f31b..c9eb7aa3 100644
--- a/freebsd/sys/netinet/ip_output.c
+++ b/freebsd/sys/netinet/ip_output.c
@@ -590,9 +590,9 @@ sendit:
}
}
- /* 127/8 must not appear on wire - RFC1122. */
- if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET ||
- (ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) {
+ /* IN_LOOPBACK must not appear on the wire - RFC1122. */
+ if (IN_LOOPBACK(ntohl(ip->ip_dst.s_addr)) ||
+ IN_LOOPBACK(ntohl(ip->ip_src.s_addr))) {
if ((ifp->if_flags & IFF_LOOPBACK) == 0) {
IPSTAT_INC(ips_badaddr);
error = EADDRNOTAVAIL;
diff --git a/freebsd/sys/netinet/raw_ip.c b/freebsd/sys/netinet/raw_ip.c
index 1cac8d12..0760fa9e 100644
--- a/freebsd/sys/netinet/raw_ip.c
+++ b/freebsd/sys/netinet/raw_ip.c
@@ -456,6 +456,8 @@ rip_output(struct mbuf *m, struct socket *so, ...)
u_long dst;
int flags = ((so->so_options & SO_DONTROUTE) ? IP_ROUTETOIF : 0) |
IP_ALLOWBROADCAST;
+ int cnt, hlen;
+ u_char opttype, optlen, *cp;
va_start(ap, so);
dst = va_arg(ap, u_long);
@@ -510,26 +512,61 @@ rip_output(struct mbuf *m, struct socket *so, ...)
m_freem(m);
return(EMSGSIZE);
}
- INP_RLOCK(inp);
ip = mtod(m, struct ip *);
- error = prison_check_ip4(inp->inp_cred, &ip->ip_src);
- if (error != 0) {
- INP_RUNLOCK(inp);
- m_freem(m);
- return (error);
+ hlen = ip->ip_hl << 2;
+ if (m->m_len < hlen) {
+ m = m_pullup(m, hlen);
+ if (m == NULL)
+ return (EINVAL);
+ ip = mtod(m, struct ip *);
}
+ INP_RLOCK(inp);
/*
* Don't allow both user specified and setsockopt options,
* and don't allow packet length sizes that will crash.
*/
- if (((ip->ip_hl != (sizeof (*ip) >> 2)) && inp->inp_options)
- || (ntohs(ip->ip_len) != m->m_pkthdr.len)
- || (ntohs(ip->ip_len) < (ip->ip_hl << 2))) {
+ if ((hlen < sizeof (*ip))
+ || ((hlen > sizeof (*ip)) && inp->inp_options)
+ || (ntohs(ip->ip_len) != m->m_pkthdr.len)) {
INP_RUNLOCK(inp);
m_freem(m);
return (EINVAL);
}
+ error = prison_check_ip4(inp->inp_cred, &ip->ip_src);
+ if (error != 0) {
+ INP_RUNLOCK(inp);
+ m_freem(m);
+ return (error);
+ }
+ /*
+ * Don't allow IP options which do not have the required
+ * structure as specified in section 3.1 of RFC 791 on
+ * pages 15-23.
+ */
+ cp = (u_char *)(ip + 1);
+ cnt = hlen - sizeof (struct ip);
+ for (; cnt > 0; cnt -= optlen, cp += optlen) {
+ opttype = cp[IPOPT_OPTVAL];
+ if (opttype == IPOPT_EOL)
+ break;
+ if (opttype == IPOPT_NOP) {
+ optlen = 1;
+ continue;
+ }
+ if (cnt < IPOPT_OLEN + sizeof(u_char)) {
+ INP_RUNLOCK(inp);
+ m_freem(m);
+ return (EINVAL);
+ }
+ optlen = cp[IPOPT_OLEN];
+ if (optlen < IPOPT_OLEN + sizeof(u_char) ||
+ optlen > cnt) {
+ INP_RUNLOCK(inp);
+ m_freem(m);
+ return (EINVAL);
+ }
+ }
/*
* This doesn't allow application to specify ID of zero,
* but we got this limitation from the beginning of history.
diff --git a/freebsd/sys/netinet/sctp.h b/freebsd/sys/netinet/sctp.h
index 64fd5442..27e5fd49 100644
--- a/freebsd/sys/netinet/sctp.h
+++ b/freebsd/sys/netinet/sctp.h
@@ -491,6 +491,7 @@ struct sctp_error_auth_invalid_hmac {
* time */
#define SCTP_SAT_NETWORK_BURST_INCR 2 /* how many times to multiply maxburst
* in sat */
+#define SCTP_MAX_SENDALL_LIMIT 1024
/* Data Chuck Specific Flags */
#define SCTP_DATA_FRAG_MASK 0x03
@@ -516,6 +517,7 @@ struct sctp_error_auth_invalid_hmac {
#define SCTP_PCB_FLAGS_BOUNDALL 0x00000004
#define SCTP_PCB_FLAGS_ACCEPTING 0x00000008
#define SCTP_PCB_FLAGS_UNBOUND 0x00000010
+#define SCTP_PCB_FLAGS_SND_ITERATOR_UP 0x00000020
#define SCTP_PCB_FLAGS_CLOSE_IP 0x00040000
#define SCTP_PCB_FLAGS_WAS_CONNECTED 0x00080000
#define SCTP_PCB_FLAGS_WAS_ABORTED 0x00100000
diff --git a/freebsd/sys/netinet/sctp_indata.c b/freebsd/sys/netinet/sctp_indata.c
index 28e3f5b2..6c2658c3 100644
--- a/freebsd/sys/netinet/sctp_indata.c
+++ b/freebsd/sys/netinet/sctp_indata.c
@@ -949,6 +949,15 @@ sctp_inject_old_unordered_data(struct sctp_tcb *stcb,
SCTPDBG(SCTP_DEBUG_XXX,
"chunk is a first fsn: %u becomes fsn_included\n",
chk->rec.data.fsn);
+ at = TAILQ_FIRST(&control->reasm);
+ if (at && SCTP_TSN_GT(chk->rec.data.fsn, at->rec.data.fsn)) {
+ /*
+ * The first chunk in the reassembly is a smaller
+ * TSN than this one, even though this has a first,
+ * it must be from a subsequent msg.
+ */
+ goto place_chunk;
+ }
if (control->first_frag_seen) {
/*
* In old un-ordered we can reassembly on one
diff --git a/freebsd/sys/netinet/sctp_output.c b/freebsd/sys/netinet/sctp_output.c
index 8d384748..cd4fcdc1 100644
--- a/freebsd/sys/netinet/sctp_output.c
+++ b/freebsd/sys/netinet/sctp_output.c
@@ -3735,6 +3735,7 @@ sctp_process_cmsgs_for_init(struct sctp_tcb *stcb, struct mbuf *control, int *er
return (0);
}
+#if defined(INET) || defined(INET6)
static struct sctp_tcb *
sctp_findassociation_cmsgs(struct sctp_inpcb **inp_p,
uint16_t port,
@@ -3824,6 +3825,7 @@ sctp_findassociation_cmsgs(struct sctp_inpcb **inp_p,
}
return (NULL);
}
+#endif
static struct mbuf *
sctp_add_cookie(struct mbuf *init, int init_offset,
@@ -4289,10 +4291,12 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
if (net->port) {
mtu -= sizeof(struct udphdr);
}
- if ((stcb != NULL) && (stcb->asoc.smallest_mtu > mtu)) {
- sctp_mtu_size_reset(inp, &stcb->asoc, mtu);
+ if (mtu < net->mtu) {
+ if ((stcb != NULL) && (stcb->asoc.smallest_mtu > mtu)) {
+ sctp_mtu_size_reset(inp, &stcb->asoc, mtu);
+ }
+ net->mtu = mtu;
}
- net->mtu = mtu;
}
} else if (ro->ro_rt == NULL) {
/* route was freed */
@@ -4647,10 +4651,12 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
if (net->port) {
mtu -= sizeof(struct udphdr);
}
- if ((stcb != NULL) && (stcb->asoc.smallest_mtu > mtu)) {
- sctp_mtu_size_reset(inp, &stcb->asoc, mtu);
+ if (mtu < net->mtu) {
+ if ((stcb != NULL) && (stcb->asoc.smallest_mtu > mtu)) {
+ sctp_mtu_size_reset(inp, &stcb->asoc, mtu);
+ }
+ net->mtu = mtu;
}
- net->mtu = mtu;
}
} else if (ifp) {
if (ND_IFINFO(ifp)->linkmtu &&
@@ -6800,15 +6806,19 @@ sctp_sendall_completes(void *ptr, uint32_t val SCTP_UNUSED)
*/
/* now free everything */
+ if (ca->inp) {
+ /* Lets clear the flag to allow others to run. */
+ ca->inp->sctp_flags &= ~SCTP_PCB_FLAGS_SND_ITERATOR_UP;
+ }
sctp_m_freem(ca->m);
SCTP_FREE(ca, SCTP_M_COPYAL);
}
static struct mbuf *
-sctp_copy_out_all(struct uio *uio, int len)
+sctp_copy_out_all(struct uio *uio, ssize_t len)
{
struct mbuf *ret, *at;
- int left, willcpy, cancpy, error;
+ ssize_t left, willcpy, cancpy, error;
ret = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_WAITOK, 1, MT_DATA);
if (ret == NULL) {
@@ -6823,17 +6833,17 @@ sctp_copy_out_all(struct uio *uio, int len)
at = ret;
while (left > 0) {
/* Align data to the end */
- error = uiomove(mtod(at, caddr_t), willcpy, uio);
+ error = uiomove(mtod(at, caddr_t), (int)willcpy, uio);
if (error) {
err_out_now:
sctp_m_freem(at);
return (NULL);
}
- SCTP_BUF_LEN(at) = willcpy;
+ SCTP_BUF_LEN(at) = (int)willcpy;
SCTP_BUF_NEXT_PKT(at) = SCTP_BUF_NEXT(at) = 0;
left -= willcpy;
if (left > 0) {
- SCTP_BUF_NEXT(at) = sctp_get_mbuf_for_msg(left, 0, M_WAITOK, 1, MT_DATA);
+ SCTP_BUF_NEXT(at) = sctp_get_mbuf_for_msg((unsigned int)left, 0, M_WAITOK, 1, MT_DATA);
if (SCTP_BUF_NEXT(at) == NULL) {
goto err_out_now;
}
@@ -6853,6 +6863,14 @@ sctp_sendall(struct sctp_inpcb *inp, struct uio *uio, struct mbuf *m,
int ret;
struct sctp_copy_all *ca;
+ if (inp->sctp_flags & SCTP_PCB_FLAGS_SND_ITERATOR_UP) {
+ /* There is another. */
+ return (EBUSY);
+ }
+ if (uio->uio_resid > SCTP_MAX_SENDALL_LIMIT) {
+ /* You must be less than the max! */
+ return (EMSGSIZE);
+ }
SCTP_MALLOC(ca, struct sctp_copy_all *, sizeof(struct sctp_copy_all),
SCTP_M_COPYAL);
if (ca == NULL) {
@@ -6873,7 +6891,7 @@ sctp_sendall(struct sctp_inpcb *inp, struct uio *uio, struct mbuf *m,
ca->sndrcv.sinfo_flags &= ~SCTP_SENDALL;
/* get length and mbuf chain */
if (uio) {
- ca->sndlen = (int)uio->uio_resid;
+ ca->sndlen = uio->uio_resid;
ca->m = sctp_copy_out_all(uio, ca->sndlen);
if (ca->m == NULL) {
SCTP_FREE(ca, SCTP_M_COPYAL);
@@ -6889,6 +6907,7 @@ sctp_sendall(struct sctp_inpcb *inp, struct uio *uio, struct mbuf *m,
ca->sndlen += SCTP_BUF_LEN(mat);
}
}
+ inp->sctp_flags |= SCTP_PCB_FLAGS_SND_ITERATOR_UP;
ret = sctp_initiate_iterator(NULL, sctp_sendall_iterator, NULL,
SCTP_PCB_ANY_FLAGS, SCTP_PCB_ANY_FEATURES,
SCTP_ASOC_ANY_STATE,
@@ -12370,7 +12389,7 @@ sctp_copy_it_in(struct sctp_tcb *stcb,
struct sctp_sndrcvinfo *srcv,
struct uio *uio,
struct sctp_nets *net,
- int max_send_len,
+ ssize_t max_send_len,
int user_marks_eor,
int *error)
{
@@ -12516,7 +12535,7 @@ sctp_lower_sosend(struct socket *so,
struct thread *p
)
{
- unsigned int sndlen = 0, max_len;
+ ssize_t sndlen = 0, max_len;
int error, len;
struct mbuf *top = NULL;
int queue_only = 0, queue_only_for_init = 0;
@@ -12538,7 +12557,8 @@ sctp_lower_sosend(struct socket *so,
int got_all_of_the_send = 0;
int hold_tcblock = 0;
int non_blocking = 0;
- uint32_t local_add_more, local_soresv = 0;
+ uint32_t local_add_more;
+ ssize_t local_soresv = 0;
uint16_t port;
uint16_t sinfo_flags;
sctp_assoc_t sinfo_assoc_id;
@@ -12568,12 +12588,12 @@ sctp_lower_sosend(struct socket *so,
SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
return (EINVAL);
}
- sndlen = (unsigned int)uio->uio_resid;
+ sndlen = uio->uio_resid;
} else {
top = SCTP_HEADER_TO_CHAIN(i_pak);
sndlen = SCTP_HEADER_LEN(i_pak);
}
- SCTPDBG(SCTP_DEBUG_OUTPUT1, "Send called addr:%p send length %d\n",
+ SCTPDBG(SCTP_DEBUG_OUTPUT1, "Send called addr:%p send length %zu\n",
(void *)addr,
sndlen);
if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
@@ -12701,9 +12721,11 @@ sctp_lower_sosend(struct socket *so,
SCTP_INP_WUNLOCK(inp);
/* With the lock applied look again */
stcb = sctp_findassociation_ep_addr(&t_inp, addr, &net, NULL, NULL);
+#if defined(INET) || defined(INET6)
if ((stcb == NULL) && (control != NULL) && (port > 0)) {
stcb = sctp_findassociation_cmsgs(&t_inp, port, control, &net, &error);
}
+#endif
if (stcb == NULL) {
SCTP_INP_WLOCK(inp);
SCTP_INP_DECR_REF(inp);
@@ -12840,7 +12862,7 @@ sctp_lower_sosend(struct socket *so,
}
/* would we block? */
if (non_blocking) {
- uint32_t amount;
+ ssize_t amount;
if (hold_tcblock == 0) {
SCTP_TCB_LOCK(stcb);
@@ -12861,7 +12883,7 @@ sctp_lower_sosend(struct socket *so,
error = EWOULDBLOCK;
goto out_unlocked;
}
- stcb->asoc.sb_send_resv += sndlen;
+ stcb->asoc.sb_send_resv += (uint32_t)sndlen;
SCTP_TCB_UNLOCK(stcb);
hold_tcblock = 0;
} else {
@@ -12927,7 +12949,7 @@ sctp_lower_sosend(struct socket *so,
/* Are we aborting? */
if (srcv->sinfo_flags & SCTP_ABORT) {
struct mbuf *mm;
- int tot_demand, tot_out = 0, max_out;
+ ssize_t tot_demand, tot_out = 0, max_out;
SCTP_STAT_INCR(sctps_sends_with_abort);
if ((SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_WAIT) ||
@@ -12961,7 +12983,7 @@ sctp_lower_sosend(struct socket *so,
error = EMSGSIZE;
goto out;
}
- mm = sctp_get_mbuf_for_msg(tot_demand, 0, M_WAITOK, 1, MT_DATA);
+ mm = sctp_get_mbuf_for_msg((unsigned int)tot_demand, 0, M_WAITOK, 1, MT_DATA);
}
if (mm == NULL) {
SCTP_LTRACE_ERR_RET(NULL, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
@@ -12981,7 +13003,7 @@ sctp_lower_sosend(struct socket *so,
ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
ph->param_length = htons((uint16_t)(sizeof(struct sctp_paramhdr) + tot_out));
ph++;
- SCTP_BUF_LEN(mm) = tot_out + sizeof(struct sctp_paramhdr);
+ SCTP_BUF_LEN(mm) = (int)(tot_out + sizeof(struct sctp_paramhdr));
if (top == NULL) {
error = uiomove((caddr_t)ph, (int)tot_out, uio);
if (error) {
@@ -13022,12 +13044,7 @@ sctp_lower_sosend(struct socket *so,
/* Calculate the maximum we can send */
inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb));
if (SCTP_SB_LIMIT_SND(so) > inqueue_bytes) {
- if (non_blocking) {
- /* we already checked for non-blocking above. */
- max_len = sndlen;
- } else {
- max_len = SCTP_SB_LIMIT_SND(so) - inqueue_bytes;
- }
+ max_len = SCTP_SB_LIMIT_SND(so) - inqueue_bytes;
} else {
max_len = 0;
}
@@ -13067,7 +13084,7 @@ sctp_lower_sosend(struct socket *so,
* For non-eeor the whole message must fit in
* the socket send buffer.
*/
- local_add_more = sndlen;
+ local_add_more = (uint32_t)sndlen;
}
len = 0;
if (non_blocking) {
@@ -13217,14 +13234,14 @@ skip_preblock:
if ((max_len > SCTP_BASE_SYSCTL(sctp_add_more_threshold)) ||
(max_len && (SCTP_SB_LIMIT_SND(so) < SCTP_BASE_SYSCTL(sctp_add_more_threshold))) ||
- (uio->uio_resid && (uio->uio_resid <= (int)max_len))) {
+ (uio->uio_resid && (uio->uio_resid <= max_len))) {
sndout = 0;
new_tail = NULL;
if (hold_tcblock) {
SCTP_TCB_UNLOCK(stcb);
hold_tcblock = 0;
}
- mm = sctp_copy_resume(uio, max_len, user_marks_eor, &error, &sndout, &new_tail);
+ mm = sctp_copy_resume(uio, (int)max_len, user_marks_eor, &error, &sndout, &new_tail);
if ((mm == NULL) || error) {
if (mm) {
sctp_m_freem(mm);
@@ -13287,7 +13304,7 @@ skip_preblock:
SCTP_TCB_LOCK(stcb);
hold_tcblock = 1;
}
- sctp_prune_prsctp(stcb, asoc, srcv, sndlen);
+ sctp_prune_prsctp(stcb, asoc, srcv, (int)sndlen);
inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb));
if (SCTP_SB_LIMIT_SND(so) > inqueue_bytes)
max_len = SCTP_SB_LIMIT_SND(so) - inqueue_bytes;
@@ -13409,7 +13426,7 @@ skip_preblock:
min(SCTP_BASE_SYSCTL(sctp_add_more_threshold), SCTP_SB_LIMIT_SND(so)))) {
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_BLK_LOGGING_ENABLE) {
sctp_log_block(SCTP_BLOCK_LOG_INTO_BLK,
- asoc, (size_t)uio->uio_resid);
+ asoc, uio->uio_resid);
}
be.error = 0;
stcb->block_entry = &be;
diff --git a/freebsd/sys/netinet/sctp_pcb.c b/freebsd/sys/netinet/sctp_pcb.c
index 782e5f1d..3d479149 100644
--- a/freebsd/sys/netinet/sctp_pcb.c
+++ b/freebsd/sys/netinet/sctp_pcb.c
@@ -4161,11 +4161,9 @@ sctp_aloc_a_assoc_id(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
struct sctpasochead *head;
struct sctp_tcb *lstcb;
- SCTP_INP_WLOCK(inp);
try_again:
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) {
/* TSNH */
- SCTP_INP_WUNLOCK(inp);
return (0);
}
/*
@@ -4184,8 +4182,7 @@ try_again:
head = &inp->sctp_asocidhash[SCTP_PCBHASH_ASOC(id, inp->hashasocidmark)];
LIST_INSERT_HEAD(head, stcb, sctp_tcbasocidhash);
stcb->asoc.in_asocid_hash = 1;
- SCTP_INP_WUNLOCK(inp);
- return id;
+ return (id);
}
/*
@@ -4348,7 +4345,6 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
memset(stcb, 0, sizeof(*stcb));
asoc = &stcb->asoc;
- asoc->assoc_id = sctp_aloc_a_assoc_id(inp, stcb);
SCTP_TCB_LOCK_INIT(stcb);
SCTP_TCB_SEND_LOCK_INIT(stcb);
stcb->rport = rport;
@@ -4359,7 +4355,6 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
/* failed */
SCTP_TCB_LOCK_DESTROY(stcb);
SCTP_TCB_SEND_LOCK_DESTROY(stcb);
- LIST_REMOVE(stcb, sctp_tcbasocidhash);
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asoc), stcb);
SCTP_DECR_ASOC_COUNT();
*error = err;
@@ -4372,7 +4367,6 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
/* inpcb freed while alloc going on */
SCTP_TCB_LOCK_DESTROY(stcb);
SCTP_TCB_SEND_LOCK_DESTROY(stcb);
- LIST_REMOVE(stcb, sctp_tcbasocidhash);
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asoc), stcb);
SCTP_INP_WUNLOCK(inp);
SCTP_INP_INFO_WUNLOCK();
@@ -4383,6 +4377,7 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
}
SCTP_TCB_LOCK(stcb);
+ asoc->assoc_id = sctp_aloc_a_assoc_id(inp, stcb);
/* now that my_vtag is set, add it to the hash */
head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(stcb->asoc.my_vtag, SCTP_BASE_INFO(hashasocmark))];
/* put it in the bucket in the vtag hash of assoc's for the system */
@@ -4991,6 +4986,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
* in case.
*/
/* anything on the wheel needs to be removed */
+ SCTP_TCB_SEND_LOCK(stcb);
for (i = 0; i < asoc->streamoutcnt; i++) {
struct sctp_stream_out *outs;
@@ -4999,7 +4995,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
TAILQ_FOREACH_SAFE(sp, &outs->outqueue, next, nsp) {
atomic_subtract_int(&asoc->stream_queue_cnt, 1);
TAILQ_REMOVE(&outs->outqueue, sp, next);
- stcb->asoc.ss_functions.sctp_ss_remove_from_stream(stcb, asoc, outs, sp, 0);
+ stcb->asoc.ss_functions.sctp_ss_remove_from_stream(stcb, asoc, outs, sp, 1);
sctp_free_spbufspace(stcb, asoc, sp);
if (sp->data) {
if (so) {
@@ -5021,6 +5017,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
sctp_free_a_strmoq(stcb, sp, SCTP_SO_LOCKED);
}
}
+ SCTP_TCB_SEND_UNLOCK(stcb);
/* sa_ignore FREED_MEMORY */
TAILQ_FOREACH_SAFE(strrst, &asoc->resetHead, next_resp, nstrrst) {
TAILQ_REMOVE(&asoc->resetHead, strrst, next_resp);
diff --git a/freebsd/sys/netinet/sctp_structs.h b/freebsd/sys/netinet/sctp_structs.h
index c4eafc26..451ae72b 100644
--- a/freebsd/sys/netinet/sctp_structs.h
+++ b/freebsd/sys/netinet/sctp_structs.h
@@ -166,7 +166,7 @@ struct sctp_copy_all {
struct sctp_inpcb *inp; /* ep */
struct mbuf *m;
struct sctp_sndrcvinfo sndrcv;
- int sndlen;
+ ssize_t sndlen;
int cnt_sent;
int cnt_failed;
};
diff --git a/freebsd/sys/netinet/sctp_usrreq.c b/freebsd/sys/netinet/sctp_usrreq.c
index 54362ed5..39132719 100644
--- a/freebsd/sys/netinet/sctp_usrreq.c
+++ b/freebsd/sys/netinet/sctp_usrreq.c
@@ -632,7 +632,6 @@ connected_type:
/* now what about control */
if (control) {
if (inp->control) {
- SCTP_PRINTF("huh? control set?\n");
sctp_m_freem(inp->control);
inp->control = NULL;
}
@@ -1124,22 +1123,25 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp,
}
#ifdef INET6
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
+ if (actual + sizeof(struct sockaddr_in6) > limit) {
+ return (actual);
+ }
in6_sin_2_v4mapsin6(sin, (struct sockaddr_in6 *)sas);
((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(struct sockaddr_in6));
actual += sizeof(struct sockaddr_in6);
} else {
#endif
- memcpy(sas, sin, sizeof(*sin));
+ if (actual + sizeof(struct sockaddr_in) > limit) {
+ return (actual);
+ }
+ memcpy(sas, sin, sizeof(struct sockaddr_in));
((struct sockaddr_in *)sas)->sin_port = inp->sctp_lport;
- sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(*sin));
- actual += sizeof(*sin);
+ sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(struct sockaddr_in));
+ actual += sizeof(struct sockaddr_in);
#ifdef INET6
}
#endif
- if (actual >= limit) {
- return (actual);
- }
} else {
continue;
}
@@ -1184,13 +1186,13 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp,
(IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) {
continue;
}
- memcpy(sas, sin6, sizeof(*sin6));
- ((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
- sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(*sin6));
- actual += sizeof(*sin6);
- if (actual >= limit) {
+ if (actual + sizeof(struct sockaddr_in6) > limit) {
return (actual);
}
+ memcpy(sas, sin6, sizeof(struct sockaddr_in6));
+ ((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
+ sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(struct sockaddr_in6));
+ actual += sizeof(struct sockaddr_in6);
} else {
continue;
}
@@ -1204,6 +1206,7 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp,
}
} else {
struct sctp_laddr *laddr;
+ size_t sa_len;
LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
if (stcb) {
@@ -1211,6 +1214,10 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp,
continue;
}
}
+ sa_len = laddr->ifa->address.sa.sa_len;
+ if (actual + sa_len > limit) {
+ return (actual);
+ }
if (sctp_fill_user_address(sas, &laddr->ifa->address.sa))
continue;
switch (laddr->ifa->address.sa.sa_family) {
@@ -1228,12 +1235,8 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp,
/* TSNH */
break;
}
- sas = (struct sockaddr_storage *)((caddr_t)sas +
- laddr->ifa->address.sa.sa_len);
- actual += laddr->ifa->address.sa.sa_len;
- if (actual >= limit) {
- return (actual);
- }
+ sas = (struct sockaddr_storage *)((caddr_t)sas + sa_len);
+ actual += sa_len;
}
}
return (actual);
@@ -1351,13 +1354,12 @@ static int
sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
size_t optsize, void *p, int delay)
{
- int error = 0;
+ int error;
int creat_lock_on = 0;
struct sctp_tcb *stcb = NULL;
struct sockaddr *sa;
unsigned int num_v6 = 0, num_v4 = 0, *totaddrp, totaddr;
uint32_t vrf_id;
- int bad_addresses = 0;
sctp_assoc_t *a_id;
SCTPDBG(SCTP_DEBUG_PCB1, "Connectx called\n");
@@ -1396,17 +1398,12 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
totaddrp = (unsigned int *)optval;
totaddr = *totaddrp;
sa = (struct sockaddr *)(totaddrp + 1);
- stcb = sctp_connectx_helper_find(inp, sa, &totaddr, &num_v4, &num_v6, &error, (unsigned int)(optsize - sizeof(int)), &bad_addresses);
- if ((stcb != NULL) || bad_addresses) {
+ error = sctp_connectx_helper_find(inp, sa, totaddr, &num_v4, &num_v6, (unsigned int)(optsize - sizeof(int)));
+ if (error != 0) {
/* Already have or am bring up an association */
SCTP_ASOC_CREATE_UNLOCK(inp);
creat_lock_on = 0;
- if (stcb)
- SCTP_TCB_UNLOCK(stcb);
- if (bad_addresses == 0) {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
- error = EALREADY;
- }
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
goto out_now;
}
#ifdef INET6
@@ -1480,8 +1477,6 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
sctp_connectx_helper_add(stcb, sa, (totaddr - 1), &error);
/* Fill in the return id */
if (error) {
- (void)sctp_free_assoc(inp, stcb, SCTP_PCBFREE_FORCE,
- SCTP_FROM_SCTP_USRREQ + SCTP_LOC_7);
goto out_now;
}
a_id = (sctp_assoc_t *)optval;
@@ -2238,8 +2233,8 @@ flags_out:
SCTP_FIND_STCB(inp, stcb, saddr->sget_assoc_id);
if (stcb) {
- left = (*optsize) - sizeof(struct sctp_getaddresses);
- *optsize = sizeof(struct sctp_getaddresses);
+ left = (*optsize) - sizeof(sctp_assoc_t);
+ *optsize = sizeof(sctp_assoc_t);
sas = (struct sockaddr_storage *)&saddr->addr[0];
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
@@ -2313,7 +2308,7 @@ flags_out:
if (stcb) {
SCTP_TCB_UNLOCK(stcb);
}
- *optsize = sizeof(struct sockaddr_storage) + actual;
+ *optsize = sizeof(sctp_assoc_t) + actual;
break;
}
case SCTP_PEER_ADDR_PARAMS:
@@ -2642,42 +2637,47 @@ flags_out:
sstat->sstat_instrms = stcb->asoc.streamincnt;
sstat->sstat_outstrms = stcb->asoc.streamoutcnt;
sstat->sstat_fragmentation_point = sctp_get_frag_point(stcb, &stcb->asoc);
- memcpy(&sstat->sstat_primary.spinfo_address,
- &stcb->asoc.primary_destination->ro._l_addr,
- ((struct sockaddr *)(&stcb->asoc.primary_destination->ro._l_addr))->sa_len);
net = stcb->asoc.primary_destination;
- ((struct sockaddr_in *)&sstat->sstat_primary.spinfo_address)->sin_port = stcb->rport;
- /*
- * Again the user can get info from sctp_constants.h
- * for what the state of the network is.
- */
- if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
- /* It's unconfirmed */
- sstat->sstat_primary.spinfo_state = SCTP_UNCONFIRMED;
- } else if (net->dest_state & SCTP_ADDR_REACHABLE) {
- /* It's active */
- sstat->sstat_primary.spinfo_state = SCTP_ACTIVE;
- } else {
- /* It's inactive */
- sstat->sstat_primary.spinfo_state = SCTP_INACTIVE;
- }
- sstat->sstat_primary.spinfo_cwnd = net->cwnd;
- sstat->sstat_primary.spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT;
- sstat->sstat_primary.spinfo_rto = net->RTO;
- sstat->sstat_primary.spinfo_mtu = net->mtu;
- switch (stcb->asoc.primary_destination->ro._l_addr.sa.sa_family) {
+ if (net != NULL) {
+ memcpy(&sstat->sstat_primary.spinfo_address,
+ &stcb->asoc.primary_destination->ro._l_addr,
+ ((struct sockaddr *)(&stcb->asoc.primary_destination->ro._l_addr))->sa_len);
+ ((struct sockaddr_in *)&sstat->sstat_primary.spinfo_address)->sin_port = stcb->rport;
+ /*
+ * Again the user can get info from
+ * sctp_constants.h for what the state of
+ * the network is.
+ */
+ if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
+ /* It's unconfirmed */
+ sstat->sstat_primary.spinfo_state = SCTP_UNCONFIRMED;
+ } else if (net->dest_state & SCTP_ADDR_REACHABLE) {
+ /* It's active */
+ sstat->sstat_primary.spinfo_state = SCTP_ACTIVE;
+ } else {
+ /* It's inactive */
+ sstat->sstat_primary.spinfo_state = SCTP_INACTIVE;
+ }
+ sstat->sstat_primary.spinfo_cwnd = net->cwnd;
+ sstat->sstat_primary.spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT;
+ sstat->sstat_primary.spinfo_rto = net->RTO;
+ sstat->sstat_primary.spinfo_mtu = net->mtu;
+ switch (stcb->asoc.primary_destination->ro._l_addr.sa.sa_family) {
#if defined(INET)
- case AF_INET:
- sstat->sstat_primary.spinfo_mtu -= SCTP_MIN_V4_OVERHEAD;
- break;
+ case AF_INET:
+ sstat->sstat_primary.spinfo_mtu -= SCTP_MIN_V4_OVERHEAD;
+ break;
#endif
#if defined(INET6)
- case AF_INET6:
- sstat->sstat_primary.spinfo_mtu -= SCTP_MIN_OVERHEAD;
- break;
+ case AF_INET6:
+ sstat->sstat_primary.spinfo_mtu -= SCTP_MIN_OVERHEAD;
+ break;
#endif
- default:
- break;
+ default:
+ break;
+ }
+ } else {
+ memset(&sstat->sstat_primary, 0, sizeof(struct sctp_paddrinfo));
}
sstat->sstat_primary.spinfo_assoc_id = sctp_get_associd(stcb);
SCTP_TCB_UNLOCK(stcb);
@@ -3744,13 +3744,11 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
uint32_t vrf_id;
if (optval == NULL) {
- SCTP_PRINTF("optval is NULL\n");
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (EINVAL);
}
inp = (struct sctp_inpcb *)so->so_pcb;
if (inp == NULL) {
- SCTP_PRINTF("inp is NULL?\n");
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (EINVAL);
}
@@ -4065,10 +4063,12 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
SCTP_FIND_STCB(inp, stcb, av->assoc_id);
if (stcb) {
+ SCTP_TCB_SEND_LOCK(stcb);
stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1);
stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
stcb->asoc.stream_scheduling_module = av->assoc_value;
stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
+ SCTP_TCB_SEND_UNLOCK(stcb);
SCTP_TCB_UNLOCK(stcb);
} else {
if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
@@ -4084,10 +4084,12 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_INP_RLOCK(inp);
LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
SCTP_TCB_LOCK(stcb);
+ SCTP_TCB_SEND_LOCK(stcb);
stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1);
stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
stcb->asoc.stream_scheduling_module = av->assoc_value;
stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
+ SCTP_TCB_SEND_UNLOCK(stcb);
SCTP_TCB_UNLOCK(stcb);
}
SCTP_INP_RUNLOCK(inp);
@@ -4624,6 +4626,12 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_TCB_UNLOCK(stcb);
break;
}
+ if (SCTP_GET_STATE(stcb) != SCTP_STATE_OPEN) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ SCTP_TCB_UNLOCK(stcb);
+ break;
+ }
if (sizeof(struct sctp_reset_streams) +
strrst->srs_number_streams * sizeof(uint16_t) > optsize) {
error = EINVAL;
@@ -4656,13 +4664,13 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
for (i = 0; i < strrst->srs_number_streams; i++) {
if ((send_in) &&
- (strrst->srs_stream_list[i] > stcb->asoc.streamincnt)) {
+ (strrst->srs_stream_list[i] >= stcb->asoc.streamincnt)) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
break;
}
if ((send_out) &&
- (strrst->srs_stream_list[i] > stcb->asoc.streamoutcnt)) {
+ (strrst->srs_stream_list[i] >= stcb->asoc.streamoutcnt)) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
break;
@@ -4738,6 +4746,12 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_TCB_UNLOCK(stcb);
break;
}
+ if (SCTP_GET_STATE(stcb) != SCTP_STATE_OPEN) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ SCTP_TCB_UNLOCK(stcb);
+ break;
+ }
if (stcb->asoc.stream_reset_outstanding) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
error = EALREADY;
@@ -4808,6 +4822,12 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_TCB_UNLOCK(stcb);
break;
}
+ if (SCTP_GET_STATE(stcb) != SCTP_STATE_OPEN) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ SCTP_TCB_UNLOCK(stcb);
+ break;
+ }
if (stcb->asoc.stream_reset_outstanding) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
error = EALREADY;
@@ -5314,10 +5334,11 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
net->dest_state &= ~SCTP_ADDR_NOHB;
}
if (paddrp->spp_flags & SPP_HB_DEMAND) {
- /* on demand HB */
- sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
- sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SOCKOPT, SCTP_SO_LOCKED);
- sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
+ if (SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) {
+ sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
+ sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SOCKOPT, SCTP_SO_LOCKED);
+ sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
+ }
}
if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
@@ -6117,6 +6138,10 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_INP_RUNLOCK(inp);
}
}
+ } else {
+ if (stcb) {
+ SCTP_TCB_UNLOCK(stcb);
+ }
}
break;
}
@@ -6211,6 +6236,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
if (info->pr_policy > SCTP_PR_SCTP_MAX) {
+ if (stcb) {
+ SCTP_TCB_UNLOCK(stcb);
+ }
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
break;
@@ -6330,6 +6358,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
}
if (thlds->spt_pathcpthld != 0xffff) {
+ if (stcb != NULL) {
+ SCTP_TCB_UNLOCK(stcb);
+ }
error = EINVAL;
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
break;
diff --git a/freebsd/sys/netinet/sctputil.c b/freebsd/sys/netinet/sctputil.c
index ddf136ef..ba7a43a0 100644
--- a/freebsd/sys/netinet/sctputil.c
+++ b/freebsd/sys/netinet/sctputil.c
@@ -548,7 +548,7 @@ sctp_wakeup_log(struct sctp_tcb *stcb, uint32_t wake_cnt, int from)
}
void
-sctp_log_block(uint8_t from, struct sctp_association *asoc, size_t sendlen)
+sctp_log_block(uint8_t from, struct sctp_association *asoc, ssize_t sendlen)
{
#if defined(SCTP_LOCAL_TRACE_BUF)
struct sctp_cwnd_log sctp_clog;
@@ -3948,7 +3948,7 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, uint16_t error, int holds_lock,
TAILQ_FOREACH_SAFE(sp, &outs->outqueue, next, nsp) {
atomic_subtract_int(&asoc->stream_queue_cnt, 1);
TAILQ_REMOVE(&outs->outqueue, sp, next);
- stcb->asoc.ss_functions.sctp_ss_remove_from_stream(stcb, asoc, outs, sp, holds_lock);
+ stcb->asoc.ss_functions.sctp_ss_remove_from_stream(stcb, asoc, outs, sp, 1);
sctp_free_spbufspace(stcb, asoc, sp);
if (sp->data) {
sctp_ulp_notify(SCTP_NOTIFY_SPECIAL_SP_FAIL, stcb,
@@ -3997,7 +3997,7 @@ sctp_abort_notification(struct sctp_tcb *stcb, uint8_t from_peer, uint16_t error
return;
}
/* Tell them we lost the asoc */
- sctp_report_all_outbound(stcb, error, 1, so_locked);
+ sctp_report_all_outbound(stcb, error, 0, so_locked);
if (from_peer) {
sctp_ulp_notify(SCTP_NOTIFY_ASSOC_REM_ABORTED, stcb, error, abort, so_locked);
} else {
@@ -5221,8 +5221,9 @@ sctp_sorecvmsg(struct socket *so,
*
*/
struct sctp_inpcb *inp = NULL;
- int my_len = 0;
- int cp_len = 0, error = 0;
+ ssize_t my_len = 0;
+ ssize_t cp_len = 0;
+ int error = 0;
struct sctp_queued_to_read *control = NULL, *ctl = NULL, *nxt = NULL;
struct mbuf *m = NULL;
struct sctp_tcb *stcb = NULL;
@@ -5231,7 +5232,7 @@ sctp_sorecvmsg(struct socket *so,
int out_flags = 0, in_flags = 0;
int block_allowed = 1;
uint32_t freed_so_far = 0;
- uint32_t copied_so_far = 0;
+ ssize_t copied_so_far = 0;
int in_eeor_mode = 0;
int no_rcv_needed = 0;
uint32_t rwnd_req = 0;
@@ -5575,7 +5576,7 @@ found_one:
* will go to the sctp_user_rcvd() that will not
* lock until it KNOWs it MUST send a WUP-SACK.
*/
- freed_so_far = stcb->freed_by_sorcv_sincelast;
+ freed_so_far = (uint32_t)stcb->freed_by_sorcv_sincelast;
stcb->freed_by_sorcv_sincelast = 0;
}
}
@@ -5730,8 +5731,8 @@ get_more_data:
m = control->data;
while (m) {
/* Move out all we can */
- cp_len = (int)uio->uio_resid;
- my_len = (int)SCTP_BUF_LEN(m);
+ cp_len = uio->uio_resid;
+ my_len = SCTP_BUF_LEN(m);
if (cp_len > my_len) {
/* not enough in this buf */
cp_len = my_len;
@@ -5741,7 +5742,7 @@ get_more_data:
hold_rlock = 0;
}
if (cp_len > 0)
- error = uiomove(mtod(m, char *), cp_len, uio);
+ error = uiomove(mtod(m, char *), (int)cp_len, uio);
/* re-read */
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
goto release;
@@ -5786,7 +5787,7 @@ get_more_data:
control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0);
}
copied_so_far += cp_len;
- freed_so_far += cp_len;
+ freed_so_far += (uint32_t)cp_len;
freed_so_far += MSIZE;
atomic_subtract_int(&control->length, cp_len);
control->data = sctp_m_free(m);
@@ -5826,9 +5827,9 @@ get_more_data:
}
if ((in_flags & MSG_PEEK) == 0) {
SCTP_BUF_RESV_UF(m, cp_len);
- SCTP_BUF_LEN(m) -= cp_len;
+ SCTP_BUF_LEN(m) -= (int)cp_len;
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
- sctp_sblog(&so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBFREE, cp_len);
+ sctp_sblog(&so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBFREE, (int)cp_len);
}
atomic_subtract_int(&so->so_rcv.sb_cc, cp_len);
if ((control->do_not_ref_stcb == 0) &&
@@ -5836,7 +5837,7 @@ get_more_data:
atomic_subtract_int(&stcb->asoc.sb_cc, cp_len);
}
copied_so_far += cp_len;
- freed_so_far += cp_len;
+ freed_so_far += (uint32_t)cp_len;
freed_so_far += MSIZE;
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
sctp_sblog(&so->so_rcv, control->do_not_ref_stcb ? NULL : stcb,
@@ -6064,7 +6065,7 @@ wait_some_more:
control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBFREE, SCTP_BUF_LEN(m));
}
sctp_sbfree(control, stcb, &so->so_rcv, m);
- freed_so_far += SCTP_BUF_LEN(m);
+ freed_so_far += (uint32_t)SCTP_BUF_LEN(m);
freed_so_far += MSIZE;
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
sctp_sblog(&so->so_rcv,
@@ -6392,30 +6393,33 @@ out_now:
return (added);
}
-struct sctp_tcb *
+int
sctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr,
- unsigned int *totaddr,
- unsigned int *num_v4, unsigned int *num_v6, int *error,
- unsigned int limit, int *bad_addr)
+ unsigned int totaddr,
+ unsigned int *num_v4, unsigned int *num_v6,
+ unsigned int limit)
{
struct sockaddr *sa;
- struct sctp_tcb *stcb = NULL;
+ struct sctp_tcb *stcb;
unsigned int incr, at, i;
at = 0;
sa = addr;
- *error = *num_v6 = *num_v4 = 0;
+ *num_v6 = *num_v4 = 0;
/* account and validate addresses */
- for (i = 0; i < *totaddr; i++) {
+ if (totaddr == 0) {
+ return (EINVAL);
+ }
+ for (i = 0; i < totaddr; i++) {
+ if (at + sizeof(struct sockaddr) > limit) {
+ return (EINVAL);
+ }
switch (sa->sa_family) {
#ifdef INET
case AF_INET:
incr = (unsigned int)sizeof(struct sockaddr_in);
if (sa->sa_len != incr) {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
- *error = EINVAL;
- *bad_addr = 1;
- return (NULL);
+ return (EINVAL);
}
(*num_v4) += 1;
break;
@@ -6428,46 +6432,34 @@ sctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr,
sin6 = (struct sockaddr_in6 *)sa;
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
/* Must be non-mapped for connectx */
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
- *error = EINVAL;
- *bad_addr = 1;
- return (NULL);
+ return (EINVAL);
}
incr = (unsigned int)sizeof(struct sockaddr_in6);
if (sa->sa_len != incr) {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
- *error = EINVAL;
- *bad_addr = 1;
- return (NULL);
+ return (EINVAL);
}
(*num_v6) += 1;
break;
}
#endif
default:
- *totaddr = i;
- incr = 0;
- /* we are done */
- break;
+ return (EINVAL);
}
- if (i == *totaddr) {
- break;
+ if ((at + incr) > limit) {
+ return (EINVAL);
}
SCTP_INP_INCR_REF(inp);
stcb = sctp_findassociation_ep_addr(&inp, sa, NULL, NULL, NULL);
if (stcb != NULL) {
- /* Already have or am bring up an association */
- return (stcb);
+ SCTP_TCB_UNLOCK(stcb);
+ return (EALREADY);
} else {
SCTP_INP_DECR_REF(inp);
}
- if ((at + incr) > limit) {
- *totaddr = i;
- break;
- }
+ at += incr;
sa = (struct sockaddr *)((caddr_t)sa + incr);
}
- return ((struct sctp_tcb *)NULL);
+ return (0);
}
/*
diff --git a/freebsd/sys/netinet/sctputil.h b/freebsd/sys/netinet/sctputil.h
index c12fb210..690e6125 100644
--- a/freebsd/sys/netinet/sctputil.h
+++ b/freebsd/sys/netinet/sctputil.h
@@ -211,10 +211,9 @@ int
sctp_connectx_helper_add(struct sctp_tcb *stcb, struct sockaddr *addr,
int totaddr, int *error);
-struct sctp_tcb *
-sctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr,
- unsigned int *totaddr, unsigned int *num_v4, unsigned int *num_v6,
- int *error, unsigned int limit, int *bad_addr);
+int
+sctp_connectx_helper_find(struct sctp_inpcb *, struct sockaddr *,
+ unsigned int, unsigned int *, unsigned int *, unsigned int);
int sctp_is_there_an_abort_here(struct mbuf *, int, uint32_t *);
#ifdef INET6
@@ -367,7 +366,7 @@ void sctp_log_closing(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int16_t loc
void sctp_log_lock(struct sctp_inpcb *inp, struct sctp_tcb *stcb, uint8_t from);
void sctp_log_maxburst(struct sctp_tcb *stcb, struct sctp_nets *, int, int, uint8_t);
-void sctp_log_block(uint8_t, struct sctp_association *, size_t);
+void sctp_log_block(uint8_t, struct sctp_association *, ssize_t);
void sctp_log_rwnd(uint8_t, uint32_t, uint32_t, uint32_t);
void sctp_log_rwnd_set(uint8_t, uint32_t, uint32_t, uint32_t, uint32_t);
int sctp_fill_stat_log(void *, size_t *);
diff --git a/freebsd/sys/netinet/tcp_input.c b/freebsd/sys/netinet/tcp_input.c
index d00504dc..77d6fc3b 100644
--- a/freebsd/sys/netinet/tcp_input.c
+++ b/freebsd/sys/netinet/tcp_input.c
@@ -2029,7 +2029,8 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
else
tp->t_flags |= TF_ACKNOW;
- if ((thflags & TH_ECE) && V_tcp_do_ecn) {
+ if (((thflags & (TH_CWR | TH_ECE)) == TH_ECE) &&
+ V_tcp_do_ecn) {
tp->t_flags |= TF_ECN_PERMIT;
TCPSTAT_INC(tcps_ecn_shs);
}
@@ -2279,6 +2280,17 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
TCPSTAT_INC(tcps_rcvpartduppack);
TCPSTAT_ADD(tcps_rcvpartdupbyte, todrop);
}
+ /*
+ * DSACK - add SACK block for dropped range
+ */
+ if (tp->t_flags & TF_SACK_PERMIT) {
+ tcp_update_sack_list(tp, th->th_seq, th->th_seq+tlen);
+ /*
+ * ACK now, as the next in-sequence segment
+ * will clear the DSACK block again
+ */
+ tp->t_flags |= TF_ACKNOW;
+ }
drop_hdrlen += todrop; /* drop from the top afterwards */
th->th_seq += todrop;
tlen -= todrop;
@@ -2403,8 +2415,8 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==
(TF_RCVD_SCALE|TF_REQ_SCALE)) {
tp->rcv_scale = tp->request_r_scale;
- tp->snd_wnd = tiwin;
}
+ tp->snd_wnd = tiwin;
/*
* Make transitions:
* SYN-RECEIVED -> ESTABLISHED
@@ -3007,6 +3019,8 @@ dodata: /* XXX */
if ((tlen || (thflags & TH_FIN) || tfo_syn) &&
TCPS_HAVERCVDFIN(tp->t_state) == 0) {
tcp_seq save_start = th->th_seq;
+ tcp_seq save_rnxt = tp->rcv_nxt;
+ int save_tlen = tlen;
m_adj(m, drop_hdrlen); /* delayed header drop */
/*
* Insert segment which includes th into TCP reassembly queue
@@ -3046,11 +3060,34 @@ dodata: /* XXX */
* m_adj() doesn't actually frees any mbufs
* when trimming from the head.
*/
- thflags = tcp_reass(tp, th, &save_start, &tlen, m);
+ tcp_seq temp = save_start;
+ thflags = tcp_reass(tp, th, &temp, &tlen, m);
tp->t_flags |= TF_ACKNOW;
}
- if (tlen > 0 && (tp->t_flags & TF_SACK_PERMIT))
- tcp_update_sack_list(tp, save_start, save_start + tlen);
+ if (tp->t_flags & TF_SACK_PERMIT) {
+ if (((tlen == 0) && (save_tlen > 0) &&
+ (SEQ_LT(save_start, save_rnxt)))) {
+ /*
+ * DSACK actually handled in the fastpath
+ * above.
+ */
+ tcp_update_sack_list(tp, save_start, save_start + save_tlen);
+ } else
+ if ((tlen > 0) && SEQ_GT(tp->rcv_nxt, save_rnxt)) {
+ /*
+ * Cleaning sackblks by using zero length
+ * update.
+ */
+ tcp_update_sack_list(tp, save_start, save_start);
+ } else
+ if ((tlen > 0) && (tlen >= save_tlen)) {
+ /* Update of sackblks. */
+ tcp_update_sack_list(tp, save_start, save_start + save_tlen);
+ } else
+ if (tlen > 0) {
+ tcp_update_sack_list(tp, save_start, save_start+tlen);
+ }
+ }
#if 0
/*
* Note the amount of data that peer has sent into
diff --git a/freebsd/sys/netinet/tcp_output.c b/freebsd/sys/netinet/tcp_output.c
index 200ae8ad..3d0a78d0 100644
--- a/freebsd/sys/netinet/tcp_output.c
+++ b/freebsd/sys/netinet/tcp_output.c
@@ -1285,15 +1285,9 @@ send:
m->m_pkthdr.tso_segsz = tp->t_maxseg - optlen;
}
-#if defined(IPSEC) || defined(IPSEC_SUPPORT)
- KASSERT(len + hdrlen + ipoptlen - ipsec_optlen == m_length(m, NULL),
- ("%s: mbuf chain shorter than expected: %d + %u + %u - %u != %u",
- __func__, len, hdrlen, ipoptlen, ipsec_optlen, m_length(m, NULL)));
-#else
- KASSERT(len + hdrlen + ipoptlen == m_length(m, NULL),
- ("%s: mbuf chain shorter than expected: %d + %u + %u != %u",
- __func__, len, hdrlen, ipoptlen, m_length(m, NULL)));
-#endif
+ KASSERT(len + hdrlen == m_length(m, NULL),
+ ("%s: mbuf chain shorter than expected: %d + %u != %u",
+ __func__, len, hdrlen, m_length(m, NULL)));
#ifdef TCP_HHOOK
/* Run HHOOK_TCP_ESTABLISHED_OUT helper hooks. */
diff --git a/freebsd/sys/netinet/tcp_sack.c b/freebsd/sys/netinet/tcp_sack.c
index 91c032c8..0f536f6c 100644
--- a/freebsd/sys/netinet/tcp_sack.c
+++ b/freebsd/sys/netinet/tcp_sack.c
@@ -170,7 +170,7 @@ tcp_update_sack_list(struct tcpcb *tp, tcp_seq rcv_start, tcp_seq rcv_end)
INP_WLOCK_ASSERT(tp->t_inpcb);
/* Check arguments. */
- KASSERT(SEQ_LT(rcv_start, rcv_end), ("rcv_start < rcv_end"));
+ KASSERT(SEQ_LEQ(rcv_start, rcv_end), ("rcv_start <= rcv_end"));
/* SACK block for the received segment. */
head_blk.start = rcv_start;
@@ -195,12 +195,54 @@ tcp_update_sack_list(struct tcpcb *tp, tcp_seq rcv_start, tcp_seq rcv_end)
* Merge this SACK block into head_blk. This SACK
* block itself will be discarded.
*/
- if (SEQ_GT(head_blk.start, start))
+ /*
+ * |-|
+ * |---| merge
+ *
+ * |-|
+ * |---| merge
+ *
+ * |-----|
+ * |-| DSACK smaller
+ *
+ * |-|
+ * |-----| DSACK smaller
+ */
+ if (head_blk.start == end)
head_blk.start = start;
- if (SEQ_LT(head_blk.end, end))
+ else if (head_blk.end == start)
head_blk.end = end;
+ else {
+ if (SEQ_LT(head_blk.start, start)) {
+ tcp_seq temp = start;
+ start = head_blk.start;
+ head_blk.start = temp;
+ }
+ if (SEQ_GT(head_blk.end, end)) {
+ tcp_seq temp = end;
+ end = head_blk.end;
+ head_blk.end = temp;
+ }
+ if ((head_blk.start != start) ||
+ (head_blk.end != end)) {
+ if ((num_saved >= 1) &&
+ SEQ_GEQ(saved_blks[num_saved-1].start, start) &&
+ SEQ_LEQ(saved_blks[num_saved-1].end, end))
+ num_saved--;
+ saved_blks[num_saved].start = start;
+ saved_blks[num_saved].end = end;
+ num_saved++;
+ }
+ }
} else {
/*
+ * This block supercedes the prior block
+ */
+ if ((num_saved >= 1) &&
+ SEQ_GEQ(saved_blks[num_saved-1].start, start) &&
+ SEQ_LEQ(saved_blks[num_saved-1].end, end))
+ num_saved--;
+ /*
* Save this SACK block.
*/
saved_blks[num_saved].start = start;
@@ -213,7 +255,7 @@ tcp_update_sack_list(struct tcpcb *tp, tcp_seq rcv_start, tcp_seq rcv_end)
* Update SACK list in tp->sackblks[].
*/
num_head = 0;
- if (SEQ_GT(head_blk.start, tp->rcv_nxt)) {
+ if (SEQ_LT(rcv_start, rcv_end)) {
/*
* The received data segment is an out-of-order segment. Put
* head_blk at the top of SACK list.
diff --git a/freebsd/sys/netinet/tcp_subr.c b/freebsd/sys/netinet/tcp_subr.c
index 52d2ca2a..db2b2661 100644
--- a/freebsd/sys/netinet/tcp_subr.c
+++ b/freebsd/sys/netinet/tcp_subr.c
@@ -1088,6 +1088,9 @@ tcp_init(void)
tcp_keepintvl = TCPTV_KEEPINTVL;
tcp_maxpersistidle = TCPTV_KEEP_IDLE;
tcp_msl = TCPTV_MSL;
+ tcp_rexmit_initial = TCPTV_RTOBASE;
+ if (tcp_rexmit_initial < 1)
+ tcp_rexmit_initial = 1;
tcp_rexmit_min = TCPTV_MIN;
if (tcp_rexmit_min < 1)
tcp_rexmit_min = 1;
@@ -1666,9 +1669,9 @@ tcp_newtcpcb(struct inpcb *inp)
* reasonable initial retransmit time.
*/
tp->t_srtt = TCPTV_SRTTBASE;
- tp->t_rttvar = ((TCPTV_RTOBASE - TCPTV_SRTTBASE) << TCP_RTTVAR_SHIFT) / 4;
+ tp->t_rttvar = ((tcp_rexmit_initial - TCPTV_SRTTBASE) << TCP_RTTVAR_SHIFT) / 4;
tp->t_rttmin = tcp_rexmit_min;
- tp->t_rxtcur = TCPTV_RTOBASE;
+ tp->t_rxtcur = tcp_rexmit_initial;
tp->snd_cwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT;
tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT;
tp->t_rcvtime = ticks;
diff --git a/freebsd/sys/netinet/tcp_syncache.c b/freebsd/sys/netinet/tcp_syncache.c
index bfbf9f42..ffdab808 100644
--- a/freebsd/sys/netinet/tcp_syncache.c
+++ b/freebsd/sys/netinet/tcp_syncache.c
@@ -156,7 +156,12 @@ static int syncookie_cmp(struct in_conninfo *inc, struct syncache_head *sch,
/*
* Transmit the SYN,ACK fewer times than TCP_MAXRXTSHIFT specifies.
- * 3 retransmits corresponds to a timeout of 3 * (1 + 2 + 4 + 8) == 45 seconds,
+ * 3 retransmits corresponds to a timeout with default values of
+ * tcp_rexmit_initial * ( 1 +
+ * tcp_backoff[1] +
+ * tcp_backoff[2] +
+ * tcp_backoff[3]) + 3 * tcp_rexmit_slop,
+ * 1000 ms * (1 + 2 + 4 + 8) + 3 * 200 ms = 15600 ms,
* the odds are that the user has given up attempting to connect by then.
*/
#define SYNCACHE_MAXREXMTS 3
@@ -421,9 +426,10 @@ syncache_timeout(struct syncache *sc, struct syncache_head *sch, int docallout)
int rexmt;
if (sc->sc_rxmits == 0)
- rexmt = TCPTV_RTOBASE;
+ rexmt = tcp_rexmit_initial;
else
- TCPT_RANGESET(rexmt, TCPTV_RTOBASE * tcp_syn_backoff[sc->sc_rxmits],
+ TCPT_RANGESET(rexmt,
+ tcp_rexmit_initial * tcp_backoff[sc->sc_rxmits],
tcp_rexmit_min, TCPTV_REXMTMAX);
sc->sc_rxttime = ticks + rexmt;
sc->sc_rxmits++;
@@ -1143,6 +1149,28 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
}
}
#endif /* TCP_SIGNATURE */
+
+ /*
+ * RFC 7323 PAWS: If we have a timestamp on this segment and
+ * it's less than ts_recent, drop it.
+ * XXXMT: RFC 7323 also requires to send an ACK.
+ * In tcp_input.c this is only done for TCP segments
+ * with user data, so be consistent here and just drop
+ * the segment.
+ */
+ if (sc->sc_flags & SCF_TIMESTAMP && to->to_flags & TOF_TS &&
+ TSTMP_LT(to->to_tsval, sc->sc_tsreflect)) {
+ SCH_UNLOCK(sch);
+ if ((s = tcp_log_addrs(inc, th, NULL, NULL))) {
+ log(LOG_DEBUG,
+ "%s; %s: SEG.TSval %u < TS.Recent %u, "
+ "segment dropped\n", s, __func__,
+ to->to_tsval, sc->sc_tsreflect);
+ free(s, M_TCPLOG);
+ }
+ return (-1); /* Do not send RST */
+ }
+
/*
* Pull out the entry to unlock the bucket row.
*
diff --git a/freebsd/sys/netinet/tcp_timer.c b/freebsd/sys/netinet/tcp_timer.c
index c50af2bb..cf6ceff5 100644
--- a/freebsd/sys/netinet/tcp_timer.c
+++ b/freebsd/sys/netinet/tcp_timer.c
@@ -112,6 +112,11 @@ int tcp_msl;
SYSCTL_PROC(_net_inet_tcp, OID_AUTO, msl, CTLTYPE_INT|CTLFLAG_RW,
&tcp_msl, 0, sysctl_msec_to_ticks, "I", "Maximum segment lifetime");
+int tcp_rexmit_initial;
+SYSCTL_PROC(_net_inet_tcp, OID_AUTO, rexmit_initial, CTLTYPE_INT|CTLFLAG_RW,
+ &tcp_rexmit_initial, 0, sysctl_msec_to_ticks, "I",
+ "Initial Retransmission Timeout");
+
int tcp_rexmit_min;
SYSCTL_PROC(_net_inet_tcp, OID_AUTO, rexmit_min, CTLTYPE_INT|CTLFLAG_RW,
&tcp_rexmit_min, 0, sysctl_msec_to_ticks, "I",
@@ -235,9 +240,6 @@ tcp_slowtimo(void)
VNET_LIST_RUNLOCK_NOSLEEP();
}
-int tcp_syn_backoff[TCP_MAXRXTSHIFT + 1] =
- { 1, 1, 1, 1, 1, 2, 4, 8, 16, 32, 64, 64, 64 };
-
int tcp_backoff[TCP_MAXRXTSHIFT + 1] =
{ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 512, 512, 512 };
@@ -673,7 +675,7 @@ tcp_timer_rexmt(void * xtp)
TCPSTAT_INC(tcps_rexmttimeo);
if ((tp->t_state == TCPS_SYN_SENT) ||
(tp->t_state == TCPS_SYN_RECEIVED))
- rexmt = TCPTV_RTOBASE * tcp_syn_backoff[tp->t_rxtshift];
+ rexmt = tcp_rexmit_initial * tcp_backoff[tp->t_rxtshift];
else
rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift];
TCPT_RANGESET(tp->t_rxtcur, rexmt,
diff --git a/freebsd/sys/netinet/tcp_timer.h b/freebsd/sys/netinet/tcp_timer.h
index a2ab6ca5..3e985bdf 100644
--- a/freebsd/sys/netinet/tcp_timer.h
+++ b/freebsd/sys/netinet/tcp_timer.h
@@ -77,7 +77,7 @@
#define TCPTV_MSL ( 30*hz) /* max seg lifetime (hah!) */
#define TCPTV_SRTTBASE 0 /* base roundtrip time;
if 0, no idea yet */
-#define TCPTV_RTOBASE ( 3*hz) /* assumed RTO if no info */
+#define TCPTV_RTOBASE ( 1*hz) /* assumed RTO if no info */
#define TCPTV_PERSMIN ( 5*hz) /* minimum persist interval */
#define TCPTV_PERSMAX ( 60*hz) /* maximum persist interval */
@@ -194,12 +194,12 @@ extern int tcp_keepintvl; /* time between keepalive probes */
extern int tcp_keepcnt; /* number of keepalives */
extern int tcp_delacktime; /* time before sending a delayed ACK */
extern int tcp_maxpersistidle;
+extern int tcp_rexmit_initial;
extern int tcp_rexmit_min;
extern int tcp_rexmit_slop;
extern int tcp_msl;
extern int tcp_ttl; /* time to live for TCP segs */
extern int tcp_backoff[];
-extern int tcp_syn_backoff[];
extern int tcp_totbackoff;
extern int tcp_rexmit_drop_options;
diff --git a/freebsd/sys/netinet/tcp_timewait.c b/freebsd/sys/netinet/tcp_timewait.c
index 8a28283f..6965d391 100644
--- a/freebsd/sys/netinet/tcp_timewait.c
+++ b/freebsd/sys/netinet/tcp_timewait.c
@@ -304,7 +304,7 @@ tcp_twstart(struct tcpcb *tp)
if (SEQ_GT(tp->rcv_adv, tp->rcv_nxt) &&
recwin < (tp->rcv_adv - tp->rcv_nxt))
recwin = (tp->rcv_adv - tp->rcv_nxt);
- tw->last_win = htons((u_short)(recwin >> tp->rcv_scale));
+ tw->last_win = (u_short)(recwin >> tp->rcv_scale);
/*
* Set t_recent if timestamps are used on the connection.
diff --git a/freebsd/sys/netinet6/in6.c b/freebsd/sys/netinet6/in6.c
index 1331d2e5..078efe45 100644
--- a/freebsd/sys/netinet6/in6.c
+++ b/freebsd/sys/netinet6/in6.c
@@ -1947,26 +1947,14 @@ in6_if_up(struct ifnet *ifp)
int
in6if_do_dad(struct ifnet *ifp)
{
+
if ((ifp->if_flags & IFF_LOOPBACK) != 0)
return (0);
-
- if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) ||
- (ND_IFINFO(ifp)->flags & ND6_IFF_NO_DAD))
+ if ((ifp->if_flags & IFF_MULTICAST) == 0)
+ return (0);
+ if ((ND_IFINFO(ifp)->flags &
+ (ND6_IFF_IFDISABLED | ND6_IFF_NO_DAD)) != 0)
return (0);
-
- /*
- * Our DAD routine requires the interface up and running.
- * However, some interfaces can be up before the RUNNING
- * status. Additionally, users may try to assign addresses
- * before the interface becomes up (or running).
- * This function returns EAGAIN in that case.
- * The caller should mark "tentative" on the address instead of
- * performing DAD immediately.
- */
- if (!((ifp->if_flags & IFF_UP) &&
- (ifp->if_drv_flags & IFF_DRV_RUNNING)))
- return (EAGAIN);
-
return (1);
}
diff --git a/freebsd/sys/netinet6/in6_ifattach.c b/freebsd/sys/netinet6/in6_ifattach.c
index 5f1128d4..956b7290 100644
--- a/freebsd/sys/netinet6/in6_ifattach.c
+++ b/freebsd/sys/netinet6/in6_ifattach.c
@@ -333,6 +333,14 @@ found:
IF_ADDR_RUNLOCK(ifp);
return -1;
+ case IFT_INFINIBAND:
+ if (addrlen != 20) {
+ IF_ADDR_RUNLOCK(ifp);
+ return -1;
+ }
+ bcopy(addr + 12, &in6->s6_addr[8], 8);
+ break;
+
default:
IF_ADDR_RUNLOCK(ifp);
return -1;
@@ -700,6 +708,7 @@ in6_ifattach(struct ifnet *ifp, struct ifnet *altifp)
* it is rather harmful to have one.
*/
ND_IFINFO(ifp)->flags &= ~ND6_IFF_AUTO_LINKLOCAL;
+ ND_IFINFO(ifp)->flags |= ND6_IFF_NO_DAD;
break;
default:
break;
diff --git a/freebsd/sys/netinet6/in6_mcast.c b/freebsd/sys/netinet6/in6_mcast.c
index ceeca992..e16de99d 100644
--- a/freebsd/sys/netinet6/in6_mcast.c
+++ b/freebsd/sys/netinet6/in6_mcast.c
@@ -2472,10 +2472,14 @@ in6p_leave_group(struct inpcb *inp, struct sockopt *sopt)
if (is_final) {
/* Remove the gap in the membership array. */
+ KASSERT(RB_EMPTY(&imf->im6f_sources),
+ ("%s: im6f_sources not empty", __func__));
for (++idx; idx < imo->im6o_num_memberships; ++idx) {
- imo->im6o_membership[idx-1] = imo->im6o_membership[idx];
- imo->im6o_mfilters[idx-1] = imo->im6o_mfilters[idx];
+ imo->im6o_membership[idx - 1] = imo->im6o_membership[idx];
+ imo->im6o_mfilters[idx - 1] = imo->im6o_mfilters[idx];
}
+ im6f_init(&imo->im6o_mfilters[idx - 1], MCAST_UNDEFINED,
+ MCAST_EXCLUDE);
imo->im6o_num_memberships--;
}
diff --git a/freebsd/sys/netinet6/in6_src.c b/freebsd/sys/netinet6/in6_src.c
index 1cb71b88..170eaf18 100644
--- a/freebsd/sys/netinet6/in6_src.c
+++ b/freebsd/sys/netinet6/in6_src.c
@@ -726,6 +726,10 @@ selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
if (ron->ro_rt == NULL ||
(ron->ro_rt->rt_flags & RTF_GATEWAY) != 0)
error = EHOSTUNREACH;
+ else {
+ rt = ron->ro_rt;
+ ifp = rt->rt_ifp;
+ }
goto done;
}
diff --git a/freebsd/sys/netinet6/ip6_output.c b/freebsd/sys/netinet6/ip6_output.c
index a0ce4027..eaae72a1 100644
--- a/freebsd/sys/netinet6/ip6_output.c
+++ b/freebsd/sys/netinet6/ip6_output.c
@@ -2218,8 +2218,11 @@ ip6_raw_ctloutput(struct socket *so, struct sockopt *sopt)
sizeof(optval));
if (error)
break;
- if ((optval % 2) != 0) {
- /* the API assumes even offset values */
+ if (optval < -1 || (optval % 2) != 0) {
+ /*
+ * The API assumes non-negative even offset
+ * values or -1 as a special value.
+ */
error = EINVAL;
} else if (so->so_proto->pr_protocol ==
IPPROTO_ICMPV6) {
diff --git a/freebsd/sys/netinet6/mld6.c b/freebsd/sys/netinet6/mld6.c
index 3b1d1afa..5b90f0a3 100644
--- a/freebsd/sys/netinet6/mld6.c
+++ b/freebsd/sys/netinet6/mld6.c
@@ -1706,6 +1706,8 @@ mld_v2_cancel_link_timers(struct mld_ifsoftc *mli)
* version, we need to release the final
* reference held for issuing the INCLUDE {}.
*/
+ if (inm->in6m_refcount == 1)
+ in6m_disconnect_locked(&inmh, inm);
in6m_rele_locked(&inmh, inm);
/* FALLTHROUGH */
case MLD_G_QUERY_PENDING_MEMBER:
diff --git a/freebsd/sys/netinet6/nd6.c b/freebsd/sys/netinet6/nd6.c
index f065815c..140dde59 100644
--- a/freebsd/sys/netinet6/nd6.c
+++ b/freebsd/sys/netinet6/nd6.c
@@ -898,6 +898,7 @@ nd6_timer(void *arg)
struct nd_prhead prl;
struct nd_defrouter *dr, *ndr;
struct nd_prefix *pr, *npr;
+ struct ifnet *ifp;
struct in6_ifaddr *ia6, *nia6;
uint64_t genid;
@@ -994,14 +995,15 @@ nd6_timer(void *arg)
* Check status of the interface. If it is down,
* mark the address as tentative for future DAD.
*/
- if ((ia6->ia_ifp->if_flags & IFF_UP) == 0 ||
- (ia6->ia_ifp->if_drv_flags & IFF_DRV_RUNNING)
- == 0 ||
- (ND_IFINFO(ia6->ia_ifp)->flags &
- ND6_IFF_IFDISABLED) != 0) {
+ ifp = ia6->ia_ifp;
+ if ((ND_IFINFO(ifp)->flags & ND6_IFF_NO_DAD) == 0 &&
+ ((ifp->if_flags & IFF_UP) == 0 ||
+ (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
+ (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) != 0)){
ia6->ia6_flags &= ~IN6_IFF_DUPLICATED;
ia6->ia6_flags |= IN6_IFF_TENTATIVE;
}
+
/*
* A new RA might have made a deprecated address
* preferred.
diff --git a/freebsd/sys/netinet6/raw_ip6.c b/freebsd/sys/netinet6/raw_ip6.c
index 73d0832a..aa62b7e1 100644
--- a/freebsd/sys/netinet6/raw_ip6.c
+++ b/freebsd/sys/netinet6/raw_ip6.c
@@ -241,9 +241,16 @@ rip6_input(struct mbuf **mp, int *offp, int proto)
}
if (in6p->in6p_cksum != -1) {
RIP6STAT_INC(rip6s_isum);
- if (in6_cksum(m, proto, *offp,
+ if (m->m_pkthdr.len - (*offp + in6p->in6p_cksum) < 2 ||
+ in6_cksum(m, proto, *offp,
m->m_pkthdr.len - *offp)) {
RIP6STAT_INC(rip6s_badsum);
+ /*
+ * Drop the received message, don't send an
+ * ICMP6 message. Set proto to IPPROTO_NONE
+ * to achieve that.
+ */
+ proto = IPPROTO_NONE;
goto skip_2;
}
}
@@ -497,7 +504,7 @@ rip6_output(struct mbuf *m, struct socket *so, ...)
off = offsetof(struct icmp6_hdr, icmp6_cksum);
else
off = in6p->in6p_cksum;
- if (plen < off + 1) {
+ if (plen < off + 2) {
error = EINVAL;
goto bad;
}
diff --git a/freebsd/sys/netipsec/xform_ah.c b/freebsd/sys/netipsec/xform_ah.c
index 84ba6c16..88e51306 100644
--- a/freebsd/sys/netipsec/xform_ah.c
+++ b/freebsd/sys/netipsec/xform_ah.c
@@ -110,6 +110,8 @@ SYSCTL_VNET_PCPUSTAT(_net_inet_ah, IPSECCTL_STATS, stats, struct ahstat,
#endif
static unsigned char ipseczeroes[256]; /* larger than an ip6 extension hdr */
+static struct timeval md5warn, ripewarn, kpdkmd5warn, kpdksha1warn;
+static struct timeval warninterval = { .tv_sec = 1, .tv_usec = 0 };
static int ah_input_cb(struct cryptop*);
static int ah_output_cb(struct cryptop*);
@@ -186,6 +188,26 @@ ah_init0(struct secasvar *sav, struct xformsw *xsp, struct cryptoini *cria)
__func__, sav->alg_auth));
return EINVAL;
}
+
+ switch (sav->alg_auth) {
+ case SADB_AALG_MD5HMAC:
+ if (ratecheck(&md5warn, &warninterval))
+ gone_in(13, "MD5-HMAC authenticator for IPsec");
+ break;
+ case SADB_X_AALG_RIPEMD160HMAC:
+ if (ratecheck(&ripewarn, &warninterval))
+ gone_in(13, "RIPEMD160-HMAC authenticator for IPsec");
+ break;
+ case SADB_X_AALG_MD5:
+ if (ratecheck(&kpdkmd5warn, &warninterval))
+ gone_in(13, "Keyed-MD5 authenticator for IPsec");
+ break;
+ case SADB_X_AALG_SHA:
+ if (ratecheck(&kpdksha1warn, &warninterval))
+ gone_in(13, "Keyed-SHA1 authenticator for IPsec");
+ break;
+ }
+
/*
* Verify the replay state block allocation is consistent with
* the protocol type. We check here so we can make assumptions
diff --git a/freebsd/sys/netipsec/xform_esp.c b/freebsd/sys/netipsec/xform_esp.c
index f8473575..d1a8a50a 100644
--- a/freebsd/sys/netipsec/xform_esp.c
+++ b/freebsd/sys/netipsec/xform_esp.c
@@ -96,6 +96,9 @@ SYSCTL_VNET_PCPUSTAT(_net_inet_esp, IPSECCTL_STATS, stats,
struct espstat, espstat,
"ESP statistics (struct espstat, netipsec/esp_var.h");
+static struct timeval deswarn, blfwarn, castwarn, camelliawarn;
+static struct timeval warninterval = { .tv_sec = 1, .tv_usec = 0 };
+
static int esp_input_cb(struct cryptop *op);
static int esp_output_cb(struct cryptop *crp);
@@ -158,6 +161,26 @@ esp_init(struct secasvar *sav, struct xformsw *xsp)
__func__));
return EINVAL;
}
+
+ switch (sav->alg_enc) {
+ case SADB_EALG_DESCBC:
+ if (ratecheck(&deswarn, &warninterval))
+ gone_in(13, "DES cipher for IPsec");
+ break;
+ case SADB_X_EALG_BLOWFISHCBC:
+ if (ratecheck(&blfwarn, &warninterval))
+ gone_in(13, "Blowfish cipher for IPsec");
+ break;
+ case SADB_X_EALG_CAST128CBC:
+ if (ratecheck(&castwarn, &warninterval))
+ gone_in(13, "CAST cipher for IPsec");
+ break;
+ case SADB_X_EALG_CAMELLIACBC:
+ if (ratecheck(&camelliawarn, &warninterval))
+ gone_in(13, "Camellia cipher for IPsec");
+ break;
+ }
+
/* subtract off the salt, RFC4106, 8.1 and RFC3686, 5.1 */
keylen = _KEYLEN(sav->key_enc) - SAV_ISCTRORGCM(sav) * 4;
if (txform->minkey > keylen || keylen > txform->maxkey) {
diff --git a/freebsd/sys/netpfil/pf/pf.c b/freebsd/sys/netpfil/pf/pf.c
index 015b2571..4f9da55b 100644
--- a/freebsd/sys/netpfil/pf/pf.c
+++ b/freebsd/sys/netpfil/pf/pf.c
@@ -6184,7 +6184,7 @@ done:
pd.proto == IPPROTO_UDP) && s != NULL && s->nat_rule.ptr != NULL &&
(s->nat_rule.ptr->action == PF_RDR ||
s->nat_rule.ptr->action == PF_BINAT) &&
- (ntohl(pd.dst->v4.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)
+ IN_LOOPBACK(ntohl(pd.dst->v4.s_addr)))
m->m_flags |= M_SKIP_FIREWALL;
if (action == PF_PASS && r->divert.port && ip_divert_ptr != NULL &&
diff --git a/freebsd/sys/netpfil/pf/pf_ioctl.c b/freebsd/sys/netpfil/pf/pf_ioctl.c
index 05cb3ccd..855ef699 100644
--- a/freebsd/sys/netpfil/pf/pf_ioctl.c
+++ b/freebsd/sys/netpfil/pf/pf_ioctl.c
@@ -3115,24 +3115,20 @@ DIOCCHANGEADDR_error:
break;
}
- PF_RULES_WLOCK();
+ PF_RULES_RLOCK();
n = pfr_table_count(&io->pfrio_table, io->pfrio_flags);
io->pfrio_size = min(io->pfrio_size, n);
+ PF_RULES_RUNLOCK();
totlen = io->pfrio_size * sizeof(struct pfr_table);
pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table),
- M_TEMP, M_NOWAIT);
- if (pfrts == NULL) {
- error = ENOMEM;
- PF_RULES_WUNLOCK();
- break;
- }
+ M_TEMP, M_WAITOK);
error = copyin(io->pfrio_buffer, pfrts, totlen);
if (error) {
free(pfrts, M_TEMP);
- PF_RULES_WUNLOCK();
break;
}
+ PF_RULES_WLOCK();
error = pfr_set_tflags(pfrts, io->pfrio_size,
io->pfrio_setflag, io->pfrio_clrflag, &io->pfrio_nchange,
&io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL);
diff --git a/freebsd/sys/netpfil/pf/pf_table.c b/freebsd/sys/netpfil/pf/pf_table.c
index 6f418985..96ed849c 100644
--- a/freebsd/sys/netpfil/pf/pf_table.c
+++ b/freebsd/sys/netpfil/pf/pf_table.c
@@ -115,6 +115,7 @@ struct pfr_walktree {
struct pfi_dynaddr *pfrw1_dyn;
} pfrw_1;
int pfrw_free;
+ int pfrw_flags;
};
#define pfrw_addr pfrw_1.pfrw1_addr
#define pfrw_astats pfrw_1.pfrw1_astats
@@ -128,15 +129,16 @@ struct pfr_walktree {
static MALLOC_DEFINE(M_PFTABLE, "pf_table", "pf(4) tables structures");
VNET_DEFINE_STATIC(uma_zone_t, pfr_kentry_z);
#define V_pfr_kentry_z VNET(pfr_kentry_z)
-VNET_DEFINE_STATIC(uma_zone_t, pfr_kcounters_z);
-#define V_pfr_kcounters_z VNET(pfr_kcounters_z)
static struct pf_addr pfr_ffaddr = {
.addr32 = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
};
+static void pfr_copyout_astats(struct pfr_astats *,
+ const struct pfr_kentry *,
+ const struct pfr_walktree *);
static void pfr_copyout_addr(struct pfr_addr *,
- struct pfr_kentry *ke);
+ const struct pfr_kentry *ke);
static int pfr_validate_addr(struct pfr_addr *);
static void pfr_enqueue_addrs(struct pfr_ktable *,
struct pfr_kentryworkq *, int *, int);
@@ -144,8 +146,12 @@ static void pfr_mark_addrs(struct pfr_ktable *);
static struct pfr_kentry
*pfr_lookup_addr(struct pfr_ktable *,
struct pfr_addr *, int);
+static bool pfr_create_kentry_counter(struct pfr_kcounters *,
+ int, int);
static struct pfr_kentry *pfr_create_kentry(struct pfr_addr *);
static void pfr_destroy_kentries(struct pfr_kentryworkq *);
+static void pfr_destroy_kentry_counter(struct pfr_kcounters *,
+ int, int);
static void pfr_destroy_kentry(struct pfr_kentry *);
static void pfr_insert_kentries(struct pfr_ktable *,
struct pfr_kentryworkq *, long);
@@ -204,9 +210,6 @@ pfr_initialize(void)
V_pfr_kentry_z = uma_zcreate("pf table entries",
sizeof(struct pfr_kentry), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR,
0);
- V_pfr_kcounters_z = uma_zcreate("pf table counters",
- sizeof(struct pfr_kcounters), NULL, NULL, NULL, NULL,
- UMA_ALIGN_PTR, 0);
V_pf_limits[PF_LIMIT_TABLE_ENTRIES].zone = V_pfr_kentry_z;
V_pf_limits[PF_LIMIT_TABLE_ENTRIES].limit = PFR_KENTRY_HIWAT;
}
@@ -216,7 +219,6 @@ pfr_cleanup(void)
{
uma_zdestroy(V_pfr_kentry_z);
- uma_zdestroy(V_pfr_kcounters_z);
}
int
@@ -610,6 +612,13 @@ pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size,
w.pfrw_op = PFRW_GET_ASTATS;
w.pfrw_astats = addr;
w.pfrw_free = kt->pfrkt_cnt;
+ /*
+ * Flags below are for backward compatibility. It was possible to have
+ * a table without per-entry counters. Now they are always allocated,
+ * we just discard data when reading it if table is not configured to
+ * have counters.
+ */
+ w.pfrw_flags = kt->pfrkt_flags;
rv = kt->pfrkt_ip4->rnh_walktree(&kt->pfrkt_ip4->rh, pfr_walktree, &w);
if (!rv)
rv = kt->pfrkt_ip6->rnh_walktree(&kt->pfrkt_ip6->rh,
@@ -776,10 +785,30 @@ pfr_lookup_addr(struct pfr_ktable *kt, struct pfr_addr *ad, int exact)
return (ke);
}
+static bool
+pfr_create_kentry_counter(struct pfr_kcounters *kc, int pfr_dir, int pfr_op)
+{
+ kc->pfrkc_packets[pfr_dir][pfr_op] = counter_u64_alloc(M_NOWAIT);
+ if (! kc->pfrkc_packets[pfr_dir][pfr_op])
+ return (false);
+
+ kc->pfrkc_bytes[pfr_dir][pfr_op] = counter_u64_alloc(M_NOWAIT);
+ if (! kc->pfrkc_bytes[pfr_dir][pfr_op]) {
+ /* Previous allocation will be freed through
+ * pfr_destroy_kentry() */
+ return (false);
+ }
+
+ kc->pfrkc_tzero = 0;
+
+ return (true);
+}
+
static struct pfr_kentry *
pfr_create_kentry(struct pfr_addr *ad)
{
struct pfr_kentry *ke;
+ int pfr_dir, pfr_op;
ke = uma_zalloc(V_pfr_kentry_z, M_NOWAIT | M_ZERO);
if (ke == NULL)
@@ -792,6 +821,14 @@ pfr_create_kentry(struct pfr_addr *ad)
ke->pfrke_af = ad->pfra_af;
ke->pfrke_net = ad->pfra_net;
ke->pfrke_not = ad->pfra_not;
+ for (pfr_dir = 0; pfr_dir < PFR_DIR_MAX; pfr_dir ++)
+ for (pfr_op = 0; pfr_op < PFR_OP_ADDR_MAX; pfr_op ++) {
+ if (! pfr_create_kentry_counter(&ke->pfrke_counters,
+ pfr_dir, pfr_op)) {
+ pfr_destroy_kentry(ke);
+ return (NULL);
+ }
+ }
return (ke);
}
@@ -807,10 +844,22 @@ pfr_destroy_kentries(struct pfr_kentryworkq *workq)
}
static void
+pfr_destroy_kentry_counter(struct pfr_kcounters *kc, int pfr_dir, int pfr_op)
+{
+ counter_u64_free(kc->pfrkc_packets[pfr_dir][pfr_op]);
+ counter_u64_free(kc->pfrkc_bytes[pfr_dir][pfr_op]);
+}
+
+static void
pfr_destroy_kentry(struct pfr_kentry *ke)
{
- if (ke->pfrke_counters)
- uma_zfree(V_pfr_kcounters_z, ke->pfrke_counters);
+ int pfr_dir, pfr_op;
+
+ for (pfr_dir = 0; pfr_dir < PFR_DIR_MAX; pfr_dir ++)
+ for (pfr_op = 0; pfr_op < PFR_OP_ADDR_MAX; pfr_op ++)
+ pfr_destroy_kentry_counter(&ke->pfrke_counters,
+ pfr_dir, pfr_op);
+
uma_zfree(V_pfr_kentry_z, ke);
}
@@ -828,7 +877,7 @@ pfr_insert_kentries(struct pfr_ktable *kt,
"(code=%d).\n", rv);
break;
}
- p->pfrke_tzero = tzero;
+ p->pfrke_counters.pfrkc_tzero = tzero;
n++;
}
kt->pfrkt_cnt += n;
@@ -851,7 +900,7 @@ pfr_insert_kentry(struct pfr_ktable *kt, struct pfr_addr *ad, long tzero)
if (rv)
return (rv);
- p->pfrke_tzero = tzero;
+ p->pfrke_counters.pfrkc_tzero = tzero;
kt->pfrkt_cnt++;
return (0);
@@ -886,15 +935,20 @@ static void
pfr_clstats_kentries(struct pfr_kentryworkq *workq, long tzero, int negchange)
{
struct pfr_kentry *p;
+ int pfr_dir, pfr_op;
SLIST_FOREACH(p, workq, pfrke_workq) {
if (negchange)
p->pfrke_not = !p->pfrke_not;
- if (p->pfrke_counters) {
- uma_zfree(V_pfr_kcounters_z, p->pfrke_counters);
- p->pfrke_counters = NULL;
+ for (pfr_dir = 0; pfr_dir < PFR_DIR_MAX; pfr_dir ++) {
+ for (pfr_op = 0; pfr_op < PFR_OP_ADDR_MAX; pfr_op ++) {
+ counter_u64_zero(p->pfrke_counters.
+ pfrkc_packets[pfr_dir][pfr_op]);
+ counter_u64_zero(p->pfrke_counters.
+ pfrkc_bytes[pfr_dir][pfr_op]);
+ }
}
- p->pfrke_tzero = tzero;
+ p->pfrke_counters.pfrkc_tzero = tzero;
}
}
@@ -983,7 +1037,7 @@ pfr_unroute_kentry(struct pfr_ktable *kt, struct pfr_kentry *ke)
}
static void
-pfr_copyout_addr(struct pfr_addr *ad, struct pfr_kentry *ke)
+pfr_copyout_addr(struct pfr_addr *ad, const struct pfr_kentry *ke)
{
bzero(ad, sizeof(*ad));
if (ke == NULL)
@@ -997,6 +1051,33 @@ pfr_copyout_addr(struct pfr_addr *ad, struct pfr_kentry *ke)
ad->pfra_ip6addr = ke->pfrke_sa.sin6.sin6_addr;
}
+static void
+pfr_copyout_astats(struct pfr_astats *as, const struct pfr_kentry *ke,
+ const struct pfr_walktree *w)
+{
+ int dir, op;
+ const struct pfr_kcounters *kc = &ke->pfrke_counters;
+
+ pfr_copyout_addr(&as->pfras_a, ke);
+ as->pfras_tzero = kc->pfrkc_tzero;
+
+ if (! (w->pfrw_flags & PFR_TFLAG_COUNTERS)) {
+ bzero(as->pfras_packets, sizeof(as->pfras_packets));
+ bzero(as->pfras_bytes, sizeof(as->pfras_bytes));
+ as->pfras_a.pfra_fback = PFR_FB_NOCOUNT;
+ return;
+ }
+
+ for (dir = 0; dir < PFR_DIR_MAX; dir ++) {
+ for (op = 0; op < PFR_OP_ADDR_MAX; op ++) {
+ as->pfras_packets[dir][op] =
+ counter_u64_fetch(kc->pfrkc_packets[dir][op]);
+ as->pfras_bytes[dir][op] =
+ counter_u64_fetch(kc->pfrkc_bytes[dir][op]);
+ }
+ }
+}
+
static int
pfr_walktree(struct radix_node *rn, void *arg)
{
@@ -1025,19 +1106,7 @@ pfr_walktree(struct radix_node *rn, void *arg)
if (w->pfrw_free-- > 0) {
struct pfr_astats as;
- pfr_copyout_addr(&as.pfras_a, ke);
-
- if (ke->pfrke_counters) {
- bcopy(ke->pfrke_counters->pfrkc_packets,
- as.pfras_packets, sizeof(as.pfras_packets));
- bcopy(ke->pfrke_counters->pfrkc_bytes,
- as.pfras_bytes, sizeof(as.pfras_bytes));
- } else {
- bzero(as.pfras_packets, sizeof(as.pfras_packets));
- bzero(as.pfras_bytes, sizeof(as.pfras_bytes));
- as.pfras_a.pfra_fback = PFR_FB_NOCOUNT;
- }
- as.pfras_tzero = ke->pfrke_tzero;
+ pfr_copyout_astats(&as, ke, w);
bcopy(&as, w->pfrw_astats, sizeof(as));
w->pfrw_astats++;
@@ -1262,6 +1331,7 @@ pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size,
struct pfr_ktableworkq workq;
int n, nn;
long tzero = time_second;
+ int pfr_dir, pfr_op;
/* XXX PFR_FLAG_CLSTATS disabled */
ACCEPT_FLAGS(flags, PFR_FLAG_ALLRSETS);
@@ -1280,7 +1350,25 @@ pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size,
continue;
if (n-- <= 0)
continue;
- bcopy(&p->pfrkt_ts, tbl++, sizeof(*tbl));
+ bcopy(&p->pfrkt_kts.pfrts_t, &tbl->pfrts_t,
+ sizeof(struct pfr_table));
+ for (pfr_dir = 0; pfr_dir < PFR_DIR_MAX; pfr_dir ++) {
+ for (pfr_op = 0; pfr_op < PFR_OP_TABLE_MAX; pfr_op ++) {
+ tbl->pfrts_packets[pfr_dir][pfr_op] =
+ counter_u64_fetch(
+ p->pfrkt_packets[pfr_dir][pfr_op]);
+ tbl->pfrts_bytes[pfr_dir][pfr_op] =
+ counter_u64_fetch(
+ p->pfrkt_bytes[pfr_dir][pfr_op]);
+ }
+ }
+ tbl->pfrts_match = counter_u64_fetch(p->pfrkt_match);
+ tbl->pfrts_nomatch = counter_u64_fetch(p->pfrkt_nomatch);
+ tbl->pfrts_tzero = p->pfrkt_tzero;
+ tbl->pfrts_cnt = p->pfrkt_cnt;
+ for (pfr_op = 0; pfr_op < PFR_REFCNT_MAX; pfr_op++)
+ tbl->pfrts_refcnt[pfr_op] = p->pfrkt_refcnt[pfr_op];
+ tbl++;
SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
}
if (flags & PFR_FLAG_CLSTATS)
@@ -1614,7 +1702,7 @@ pfr_commit_ktable(struct pfr_ktable *kt, long tzero)
q->pfrke_mark = 1;
SLIST_INSERT_HEAD(&garbageq, p, pfrke_workq);
} else {
- p->pfrke_tzero = tzero;
+ p->pfrke_counters.pfrkc_tzero = tzero;
SLIST_INSERT_HEAD(&addq, p, pfrke_workq);
}
}
@@ -1798,14 +1886,20 @@ static void
pfr_clstats_ktable(struct pfr_ktable *kt, long tzero, int recurse)
{
struct pfr_kentryworkq addrq;
+ int pfr_dir, pfr_op;
if (recurse) {
pfr_enqueue_addrs(kt, &addrq, NULL, 0);
pfr_clstats_kentries(&addrq, tzero, 0);
}
- bzero(kt->pfrkt_packets, sizeof(kt->pfrkt_packets));
- bzero(kt->pfrkt_bytes, sizeof(kt->pfrkt_bytes));
- kt->pfrkt_match = kt->pfrkt_nomatch = 0;
+ for (pfr_dir = 0; pfr_dir < PFR_DIR_MAX; pfr_dir ++) {
+ for (pfr_op = 0; pfr_op < PFR_OP_TABLE_MAX; pfr_op ++) {
+ counter_u64_zero(kt->pfrkt_packets[pfr_dir][pfr_op]);
+ counter_u64_zero(kt->pfrkt_bytes[pfr_dir][pfr_op]);
+ }
+ }
+ counter_u64_zero(kt->pfrkt_match);
+ counter_u64_zero(kt->pfrkt_nomatch);
kt->pfrkt_tzero = tzero;
}
@@ -1814,6 +1908,7 @@ pfr_create_ktable(struct pfr_table *tbl, long tzero, int attachruleset)
{
struct pfr_ktable *kt;
struct pf_ruleset *rs;
+ int pfr_dir, pfr_op;
PF_RULES_WASSERT();
@@ -1832,6 +1927,34 @@ pfr_create_ktable(struct pfr_table *tbl, long tzero, int attachruleset)
rs->tables++;
}
+ for (pfr_dir = 0; pfr_dir < PFR_DIR_MAX; pfr_dir ++) {
+ for (pfr_op = 0; pfr_op < PFR_OP_TABLE_MAX; pfr_op ++) {
+ kt->pfrkt_packets[pfr_dir][pfr_op] =
+ counter_u64_alloc(M_NOWAIT);
+ if (! kt->pfrkt_packets[pfr_dir][pfr_op]) {
+ pfr_destroy_ktable(kt, 0);
+ return (NULL);
+ }
+ kt->pfrkt_bytes[pfr_dir][pfr_op] =
+ counter_u64_alloc(M_NOWAIT);
+ if (! kt->pfrkt_bytes[pfr_dir][pfr_op]) {
+ pfr_destroy_ktable(kt, 0);
+ return (NULL);
+ }
+ }
+ }
+ kt->pfrkt_match = counter_u64_alloc(M_NOWAIT);
+ if (! kt->pfrkt_match) {
+ pfr_destroy_ktable(kt, 0);
+ return (NULL);
+ }
+
+ kt->pfrkt_nomatch = counter_u64_alloc(M_NOWAIT);
+ if (! kt->pfrkt_nomatch) {
+ pfr_destroy_ktable(kt, 0);
+ return (NULL);
+ }
+
if (!rn_inithead((void **)&kt->pfrkt_ip4,
offsetof(struct sockaddr_in, sin_addr) * 8) ||
!rn_inithead((void **)&kt->pfrkt_ip6,
@@ -1859,6 +1982,7 @@ static void
pfr_destroy_ktable(struct pfr_ktable *kt, int flushaddr)
{
struct pfr_kentryworkq addrq;
+ int pfr_dir, pfr_op;
if (flushaddr) {
pfr_enqueue_addrs(kt, &addrq, NULL, 0);
@@ -1875,6 +1999,15 @@ pfr_destroy_ktable(struct pfr_ktable *kt, int flushaddr)
kt->pfrkt_rs->tables--;
pf_remove_if_empty_ruleset(kt->pfrkt_rs);
}
+ for (pfr_dir = 0; pfr_dir < PFR_DIR_MAX; pfr_dir ++) {
+ for (pfr_op = 0; pfr_op < PFR_OP_TABLE_MAX; pfr_op ++) {
+ counter_u64_free(kt->pfrkt_packets[pfr_dir][pfr_op]);
+ counter_u64_free(kt->pfrkt_bytes[pfr_dir][pfr_op]);
+ }
+ }
+ counter_u64_free(kt->pfrkt_match);
+ counter_u64_free(kt->pfrkt_nomatch);
+
free(kt, M_PFTABLE);
}
@@ -1943,9 +2076,9 @@ pfr_match_addr(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af)
}
match = (ke && !ke->pfrke_not);
if (match)
- kt->pfrkt_match++;
+ counter_u64_add(kt->pfrkt_match, 1);
else
- kt->pfrkt_nomatch++;
+ counter_u64_add(kt->pfrkt_nomatch, 1);
return (match);
}
@@ -2000,17 +2133,14 @@ pfr_update_stats(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af,
("pfr_update_stats: assertion failed.\n"));
op_pass = PFR_OP_XPASS;
}
- kt->pfrkt_packets[dir_out][op_pass]++;
- kt->pfrkt_bytes[dir_out][op_pass] += len;
+ counter_u64_add(kt->pfrkt_packets[dir_out][op_pass], 1);
+ counter_u64_add(kt->pfrkt_bytes[dir_out][op_pass], len);
if (ke != NULL && op_pass != PFR_OP_XPASS &&
(kt->pfrkt_flags & PFR_TFLAG_COUNTERS)) {
- if (ke->pfrke_counters == NULL)
- ke->pfrke_counters = uma_zalloc(V_pfr_kcounters_z,
- M_NOWAIT | M_ZERO);
- if (ke->pfrke_counters != NULL) {
- ke->pfrke_counters->pfrkc_packets[dir_out][op_pass]++;
- ke->pfrke_counters->pfrkc_bytes[dir_out][op_pass] += len;
- }
+ counter_u64_add(ke->pfrke_counters.
+ pfrkc_packets[dir_out][op_pass], 1);
+ counter_u64_add(ke->pfrke_counters.
+ pfrkc_bytes[dir_out][op_pass], len);
}
}
@@ -2100,7 +2230,7 @@ pfr_pool_get(struct pfr_ktable *kt, int *pidx, struct pf_addr *counter,
_next_block:
ke = pfr_kentry_byidx(kt, idx, af);
if (ke == NULL) {
- kt->pfrkt_nomatch++;
+ counter_u64_add(kt->pfrkt_nomatch, 1);
return (1);
}
pfr_prepare_network(&umask, af, ke->pfrke_net);
@@ -2125,7 +2255,7 @@ _next_block:
/* this is a single IP address - no possible nested block */
PF_ACPY(counter, addr, af);
*pidx = idx;
- kt->pfrkt_match++;
+ counter_u64_add(kt->pfrkt_match, 1);
return (0);
}
for (;;) {
@@ -2145,7 +2275,7 @@ _next_block:
/* lookup return the same block - perfect */
PF_ACPY(counter, addr, af);
*pidx = idx;
- kt->pfrkt_match++;
+ counter_u64_add(kt->pfrkt_match, 1);
return (0);
}
diff --git a/freebsd/sys/opencrypto/cbc_mac.c b/freebsd/sys/opencrypto/cbc_mac.c
index e68525ef..1bcf356a 100644
--- a/freebsd/sys/opencrypto/cbc_mac.c
+++ b/freebsd/sys/opencrypto/cbc_mac.c
@@ -84,9 +84,6 @@ AES_CBC_MAC_Reinit(struct aes_cbc_mac_ctx *ctx, const uint8_t *nonce, uint16_t n
uint8_t *bp = b0, flags = 0;
uint8_t L = 0;
uint64_t dataLength = ctx->cryptDataLength;
-
- KASSERT(ctx->authDataLength != 0 || ctx->cryptDataLength != 0,
- ("Auth Data and Data lengths cannot both be 0"));
KASSERT(nonceLen >= 7 && nonceLen <= 13,
("nonceLen must be between 7 and 13 bytes"));
diff --git a/freebsd/sys/powerpc/include/machine/spr.h b/freebsd/sys/powerpc/include/machine/spr.h
index 8fa828e1..9b13c291 100644
--- a/freebsd/sys/powerpc/include/machine/spr.h
+++ b/freebsd/sys/powerpc/include/machine/spr.h
@@ -242,6 +242,8 @@
#define LPCR_PECE_ME (1ULL << 12) /* Machine Check and Hypervisor */
/* Maintenance exceptions */
#define SPR_LPID 0x13f /* Logical Partitioning Control */
+#define SPR_HMER 0x150 /* Hypervisor Maintenance Exception Register */
+#define SPR_HMEER 0x151 /* Hypervisor Maintenance Exception Enable Register */
#define SPR_PTCR 0x1d0 /* Partition Table Control Register */
#define SPR_SPEFSCR 0x200 /* ..8 Signal Processing Engine FSCR. */
diff --git a/freebsd/sys/sys/ata.h b/freebsd/sys/sys/ata.h
index f8a332c3..0559b35d 100644
--- a/freebsd/sys/sys/ata.h
+++ b/freebsd/sys/sys/ata.h
@@ -393,6 +393,12 @@ struct ata_params {
#define ATA_READ_LOG_DMA_EXT 0x47 /* read log DMA ext - PIO Data-In */
#define ATA_ZAC_MANAGEMENT_IN 0x4a /* ZAC management in */
#define ATA_ZM_REPORT_ZONES 0x00 /* report zones */
+#define ATA_WRITE_LOG_DMA_EXT 0x57 /* WRITE LOG DMA EXT */
+#define ATA_TRUSTED_NON_DATA 0x5b /* TRUSTED NON-DATA */
+#define ATA_TRUSTED_RECEIVE 0x5c /* TRUSTED RECEIVE */
+#define ATA_TRUSTED_RECEIVE_DMA 0x5d /* TRUSTED RECEIVE DMA */
+#define ATA_TRUSTED_SEND 0x5e /* TRUSTED SEND */
+#define ATA_TRUSTED_SEND_DMA 0x5f /* TRUSTED SEND DMA */
#define ATA_READ_FPDMA_QUEUED 0x60 /* read DMA NCQ */
#define ATA_WRITE_FPDMA_QUEUED 0x61 /* write DMA NCQ */
#define ATA_NCQ_NON_DATA 0x63 /* NCQ non-data command */
@@ -417,6 +423,8 @@ struct ata_params {
#define ATA_ZM_FINISH_ZONE 0x02 /* finish zone */
#define ATA_ZM_OPEN_ZONE 0x03 /* open zone */
#define ATA_ZM_RWP 0x04 /* reset write pointer */
+#define ATA_DOWNLOAD_MICROCODE 0x92 /* DOWNLOAD MICROCODE */
+#define ATA_DOWNLOAD_MICROCODE_DMA 0x93 /* DOWNLOAD MICROCODE DMA */
#define ATA_PACKET_CMD 0xa0 /* packet command */
#define ATA_ATAPI_IDENTIFY 0xa1 /* get ATAPI params*/
#define ATA_SERVICE 0xa2 /* service command */
@@ -439,8 +447,11 @@ struct ata_params {
#define ATA_CHECK_POWER_MODE 0xe5 /* device power mode */
#define ATA_SLEEP 0xe6 /* sleep */
#define ATA_FLUSHCACHE 0xe7 /* flush cache to disk */
+#define ATA_WRITE_BUFFER 0xe8 /* write buffer */
#define ATA_WRITE_PM 0xe8 /* write portmultiplier */
+#define ATA_READ_BUFFER_DMA 0xe9 /* read buffer DMA */
#define ATA_FLUSHCACHE48 0xea /* flush cache to disk */
+#define ATA_WRITE_BUFFER_DMA 0xeb /* write buffer DMA */
#define ATA_ATA_IDENTIFY 0xec /* get ATA params */
#define ATA_SETFEATURES 0xef /* features command */
#define ATA_SF_ENAB_WCACHE 0x02 /* enable write cache */
diff --git a/freebsd/sys/sys/bus.h b/freebsd/sys/sys/bus.h
index 0159b829..e2c4fe1a 100644
--- a/freebsd/sys/sys/bus.h
+++ b/freebsd/sys/sys/bus.h
@@ -130,6 +130,7 @@ struct devreq {
#define DEV_DELETE _IOW('D', 10, struct devreq)
#define DEV_FREEZE _IOW('D', 11, struct devreq)
#define DEV_THAW _IOW('D', 12, struct devreq)
+#define DEV_RESET _IOW('D', 13, struct devreq)
/* Flags for DEV_DETACH and DEV_DISABLE. */
#define DEVF_FORCE_DETACH 0x0000001
@@ -143,6 +144,10 @@ struct devreq {
/* Flags for DEV_DELETE. */
#define DEVF_FORCE_DELETE 0x0000001
+/* Flags for DEV_RESET */
+#define DEVF_RESET_DETACH 0x0000001 /* Detach drivers vs suspend
+ device */
+
#ifdef _KERNEL
#include <sys/eventhandler.h>
@@ -494,6 +499,8 @@ int bus_generic_unmap_resource(device_t dev, device_t child, int type,
struct resource_map *map);
int bus_generic_write_ivar(device_t dev, device_t child, int which,
uintptr_t value);
+int bus_helper_reset_post(device_t dev, int flags);
+int bus_helper_reset_prepare(device_t dev, int flags);
int bus_null_rescan(device_t dev);
/*
diff --git a/freebsd/sys/sys/capsicum.h b/freebsd/sys/sys/capsicum.h
index d40b8572..ee5e4267 100644
--- a/freebsd/sys/sys/capsicum.h
+++ b/freebsd/sys/sys/capsicum.h
@@ -246,7 +246,12 @@
/* Process management via process descriptors. */
/* Allows for pdgetpid(2). */
#define CAP_PDGETPID CAPRIGHT(1, 0x0000000000000200ULL)
-/* Allows for pdwait4(2). */
+/*
+ * Allows for pdwait4(2).
+ *
+ * XXX: this constant was imported unused, but is targeted to be implemented
+ * in the future (bug 235871).
+ */
#define CAP_PDWAIT CAPRIGHT(1, 0x0000000000000400ULL)
/* Allows for pdkill(2). */
#define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL)
diff --git a/freebsd/sys/sys/ctype.h b/freebsd/sys/sys/ctype.h
index b2a1fa93..d542e45a 100644
--- a/freebsd/sys/sys/ctype.h
+++ b/freebsd/sys/sys/ctype.h
@@ -41,19 +41,65 @@
#ifdef _KERNEL
-#define isspace(c) ((c) == ' ' || ((c) >= '\t' && (c) <= '\r'))
-#define isascii(c) (((c) & ~0x7f) == 0)
-#define isupper(c) ((c) >= 'A' && (c) <= 'Z')
-#define islower(c) ((c) >= 'a' && (c) <= 'z')
-#define isalpha(c) (isupper(c) || islower(c))
-#define isdigit(c) ((c) >= '0' && (c) <= '9')
-#define isxdigit(c) (isdigit(c) \
- || ((c) >= 'A' && (c) <= 'F') \
- || ((c) >= 'a' && (c) <= 'f'))
-#define isprint(c) ((c) >= ' ' && (c) <= '~')
-
-#define toupper(c) ((c) - 0x20 * (((c) >= 'a') && ((c) <= 'z')))
-#define tolower(c) ((c) + 0x20 * (((c) >= 'A') && ((c) <= 'Z')))
+static __inline int
+isspace(int c)
+{
+ return (c == ' ' || (c >= '\t' && c <= '\r'));
+}
+
+static __inline int
+isascii(int c)
+{
+ return ((c & ~0x7f) == 0);
+}
+
+static __inline int
+isupper(int c)
+{
+ return (c >= 'A' && c <= 'Z');
+}
+
+static __inline int
+islower(int c)
+{
+ return (c >= 'a' && c <= 'z');
+}
+
+static __inline int
+isalpha(int c)
+{
+ return (isupper(c) || islower(c));
+}
+
+static __inline int
+isdigit(int c)
+{
+ return (c >= '0' && c <= '9');
+}
+
+static __inline int
+isxdigit(int c)
+{
+ return (isdigit(c) || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'));
+}
+
+static __inline int
+isprint(int c)
+{
+ return (c >= ' ' && c <= '~');
+}
+
+static __inline int
+toupper(int c)
+{
+ return (c - 0x20 * ((c >= 'a') && (c <= 'z')));
+}
+
+static __inline int
+tolower(int c)
+{
+ return (c + 0x20 * ((c >= 'A') && (c <= 'Z')));
+}
#endif
#endif /* !_SYS_CTYPE_H_ */
diff --git a/freebsd/sys/sys/libkern.h b/freebsd/sys/sys/libkern.h
index 28da25ca..8e63fa2d 100644
--- a/freebsd/sys/sys/libkern.h
+++ b/freebsd/sys/sys/libkern.h
@@ -230,6 +230,7 @@ char *strchr(const char *, int);
int strcmp(const char *, const char *);
char *strcpy(char * __restrict, const char * __restrict);
size_t strcspn(const char * __restrict, const char * __restrict) __pure;
+char *strdup_flags(const char *__restrict, struct malloc_type *, int);
#ifdef __rtems__
#include <string.h>
#define strdup _bsd_strdup
diff --git a/freebsd/sys/sys/random.h b/freebsd/sys/sys/random.h
index 32d8122d..866d658b 100644
--- a/freebsd/sys/sys/random.h
+++ b/freebsd/sys/sys/random.h
@@ -100,6 +100,7 @@ enum random_entropy_source {
RANDOM_PURE_BROADCOM,
RANDOM_PURE_CCP,
RANDOM_PURE_DARN,
+ RANDOM_PURE_TPM,
ENTROPYSOURCE
};
diff --git a/freebsd/sys/sys/seq.h b/freebsd/sys/sys/seq.h
index c5f00bcb..657edf4d 100644
--- a/freebsd/sys/sys/seq.h
+++ b/freebsd/sys/sys/seq.h
@@ -121,7 +121,7 @@ seq_write_end(seq_t *seqp)
}
static __inline seq_t
-seq_read(const seq_t *seqp)
+seq_load(const seq_t *seqp)
{
seq_t ret;
diff --git a/freebsd/sys/sys/slicer.h b/freebsd/sys/sys/slicer.h
index 1565ecce..675b5acc 100644
--- a/freebsd/sys/sys/slicer.h
+++ b/freebsd/sys/sys/slicer.h
@@ -58,7 +58,7 @@ typedef int (*flash_slicer_t)(device_t dev, const char *provider,
#define FLASH_SLICES_TYPE_SPI 2
#define FLASH_SLICES_TYPE_MMC 3
-/* Use NULL for deregistering a slicer */
+/* Use NULL and set force to true for deregistering a slicer */
void flash_register_slicer(flash_slicer_t slicer, u_int type, bool force);
#endif /* _KERNEL */
diff --git a/freebsd/sys/sys/sysctl.h b/freebsd/sys/sys/sysctl.h
index a0aa8f75..4b2bfd76 100644
--- a/freebsd/sys/sys/sysctl.h
+++ b/freebsd/sys/sys/sysctl.h
@@ -388,6 +388,25 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry);
NULL); \
})
+/* Oid for a constant '\0' terminated string. */
+#define SYSCTL_CONST_STRING(parent, nbr, name, access, arg, descr) \
+ SYSCTL_OID(parent, nbr, name, CTLTYPE_STRING|(access), \
+ __DECONST(char *, arg), 0, sysctl_handle_string, "A", descr); \
+ CTASSERT(!(access & CTLFLAG_WR)); \
+ CTASSERT(((access) & CTLTYPE) == 0 || \
+ ((access) & SYSCTL_CT_ASSERT_MASK) == CTLTYPE_STRING)
+
+#define SYSCTL_ADD_CONST_STRING(ctx, parent, nbr, name, access, arg, descr) \
+({ \
+ char *__arg = __DECONST(char *, arg); \
+ CTASSERT(!(access & CTLFLAG_WR)); \
+ CTASSERT(((access) & CTLTYPE) == 0 || \
+ ((access) & SYSCTL_CT_ASSERT_MASK) == CTLTYPE_STRING); \
+ sysctl_add_oid(ctx, parent, nbr, name, CTLTYPE_STRING|(access), \
+ __arg, 0, sysctl_handle_string, "A", __DESCR(descr), \
+ NULL); \
+})
+
/* Oid for a bool. If ptr is NULL, val is returned. */
#define SYSCTL_NULL_BOOL_PTR ((bool *)NULL)
#define SYSCTL_BOOL(parent, nbr, name, access, ptr, val, descr) \
diff --git a/freebsd/sys/sys/systm.h b/freebsd/sys/sys/systm.h
index cbd9a7e8..ae25b843 100644
--- a/freebsd/sys/sys/systm.h
+++ b/freebsd/sys/sys/systm.h
@@ -688,6 +688,7 @@ void counted_warning(unsigned *counter, const char *msg);
/*
* APIs to manage deprecation and obsolescence.
*/
+#ifndef __rtems__
struct device;
void _gone_in(int major, const char *msg);
void _gone_in_dev(struct device *dev, int major, const char *msg);
@@ -703,6 +704,10 @@ void _gone_in_dev(struct device *dev, int major, const char *msg);
#define gone_by_fcp101_dev(dev) \
gone_in_dev((dev), 13, \
"see https://github.com/freebsd/fcp/blob/master/fcp-0101.md")
+#else /* __rtems__ */
+#define gone_in(major, msg) do { } while (0)
+#define gone_in_dev(dev, major, msg) do { } while (0)
+#endif /* __rtems__ */
__NULLABILITY_PRAGMA_POP
diff --git a/freebsd/sys/sys/user.h b/freebsd/sys/sys/user.h
index a46ecd87..b2338f01 100644
--- a/freebsd/sys/sys/user.h
+++ b/freebsd/sys/sys/user.h
@@ -614,6 +614,7 @@ int kern_proc_vmmap_out(struct proc *p, struct sbuf *sb, ssize_t maxlen,
int flags);
int vntype_to_kinfo(int vtype);
+void pack_kinfo(struct kinfo_file *kif);
#endif /* !_KERNEL */
#endif
diff --git a/freebsd/sys/sys/vnode.h b/freebsd/sys/sys/vnode.h
index ac6f4f4e..1cc67ecf 100644
--- a/freebsd/sys/sys/vnode.h
+++ b/freebsd/sys/sys/vnode.h
@@ -670,6 +670,7 @@ int vn_close(struct vnode *vp,
int flags, struct ucred *file_cred, struct thread *td);
void vn_finished_write(struct mount *mp);
void vn_finished_secondary_write(struct mount *mp);
+int vn_fsync_buf(struct vnode *vp, int waitfor);
int vn_isdisk(struct vnode *vp, int *errp);
int _vn_lock(struct vnode *vp, int flags, char *file, int line);
#define vn_lock(vp, flags) _vn_lock(vp, flags, __FILE__, __LINE__)
diff --git a/freebsd/sys/x86/include/machine/bus.h b/freebsd/sys/x86/include/machine/bus.h
index 297b5edc..2427ae51 100644
--- a/freebsd/sys/x86/include/machine/bus.h
+++ b/freebsd/sys/x86/include/machine/bus.h
@@ -114,7 +114,11 @@
#define BUS_SPACE_MAXSIZE_24BIT 0xFFFFFF
#define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF
+#if defined(__amd64__)
+#define BUS_SPACE_MAXSIZE 0xFFFFFFFFFFFFFFFFULL
+#else
#define BUS_SPACE_MAXSIZE 0xFFFFFFFF
+#endif
#define BUS_SPACE_MAXADDR_24BIT 0xFFFFFF
#define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF
#if defined(__amd64__) || defined(PAE)
diff --git a/freebsd/sys/x86/include/machine/pci_cfgreg.h b/freebsd/sys/x86/include/machine/pci_cfgreg.h
index 8083eb0e..85d6485c 100644
--- a/freebsd/sys/x86/include/machine/pci_cfgreg.h
+++ b/freebsd/sys/x86/include/machine/pci_cfgreg.h
@@ -48,6 +48,15 @@
#define CONF2_ENABLE_CHK 0x0e
#define CONF2_ENABLE_RES 0x0e
+enum {
+ CFGMECH_NONE = 0,
+ CFGMECH_1,
+ CFGMECH_2,
+ CFGMECH_PCIE,
+};
+
+extern int cfgmech;
+
rman_res_t hostb_alloc_start(int type, rman_res_t start, rman_res_t end, rman_res_t count);
int pcie_cfgregopen(uint64_t base, uint8_t minbus, uint8_t maxbus);
int pci_cfgregopen(void);
diff --git a/freebsd/usr.bin/netstat/inet.c b/freebsd/usr.bin/netstat/inet.c
index 4eb80816..73d3ec65 100644
--- a/freebsd/usr.bin/netstat/inet.c
+++ b/freebsd/usr.bin/netstat/inet.c
@@ -97,8 +97,10 @@ __FBSDID("$FreeBSD$");
#include "rtems-bsd-netstat-inet-data.h"
#endif /* __rtems__ */
-void inetprint(const char *, struct in_addr *, int, const char *, int,
+#ifdef INET
+static void inetprint(const char *, struct in_addr *, int, const char *, int,
const int);
+#endif
#ifdef INET6
static int udp_done, tcp_done, sdp_done;
#endif /* INET6 */
@@ -412,6 +414,7 @@ protopr(u_long off, const char *name, int af1, int proto)
so->so_rcv.sb_cc, so->so_snd.sb_cc);
}
if (numeric_port) {
+#ifdef INET
if (inp->inp_vflag & INP_IPV4) {
inetprint("local", &inp->inp_laddr,
(int)inp->inp_lport, name, 1, af1);
@@ -419,8 +422,12 @@ protopr(u_long off, const char *name, int af1, int proto)
inetprint("remote", &inp->inp_faddr,
(int)inp->inp_fport, name, 1, af1);
}
+#endif
+#if defined(INET) && defined(INET6)
+ else
+#endif
#ifdef INET6
- else if (inp->inp_vflag & INP_IPV6) {
+ if (inp->inp_vflag & INP_IPV6) {
inet6print("local", &inp->in6p_laddr,
(int)inp->inp_lport, name, 1);
if (!Lflag)
@@ -429,6 +436,7 @@ protopr(u_long off, const char *name, int af1, int proto)
} /* else nothing printed now */
#endif /* INET6 */
} else if (inp->inp_flags & INP_ANONPORT) {
+#ifdef INET
if (inp->inp_vflag & INP_IPV4) {
inetprint("local", &inp->inp_laddr,
(int)inp->inp_lport, name, 1, af1);
@@ -436,8 +444,12 @@ protopr(u_long off, const char *name, int af1, int proto)
inetprint("remote", &inp->inp_faddr,
(int)inp->inp_fport, name, 0, af1);
}
+#endif
+#if defined(INET) && defined(INET6)
+ else
+#endif
#ifdef INET6
- else if (inp->inp_vflag & INP_IPV6) {
+ if (inp->inp_vflag & INP_IPV6) {
inet6print("local", &inp->in6p_laddr,
(int)inp->inp_lport, name, 1);
if (!Lflag)
@@ -446,6 +458,7 @@ protopr(u_long off, const char *name, int af1, int proto)
} /* else nothing printed now */
#endif /* INET6 */
} else {
+#ifdef INET
if (inp->inp_vflag & INP_IPV4) {
inetprint("local", &inp->inp_laddr,
(int)inp->inp_lport, name, 0, af1);
@@ -455,8 +468,12 @@ protopr(u_long off, const char *name, int af1, int proto)
inp->inp_lport != inp->inp_fport,
af1);
}
+#endif
+#if defined(INET) && defined(INET6)
+ else
+#endif
#ifdef INET6
- else if (inp->inp_vflag & INP_IPV6) {
+ if (inp->inp_vflag & INP_IPV6) {
inet6print("local", &inp->in6p_laddr,
(int)inp->inp_lport, name, 0);
if (!Lflag)
@@ -1340,10 +1357,11 @@ pim_stats(u_long off __unused, const char *name, int af1 __unused,
xo_close_container(name);
}
+#ifdef INET
/*
* Pretty print an Internet address (net address + port).
*/
-void
+static void
inetprint(const char *container, struct in_addr *in, int port,
const char *proto, int num_port, const int af1)
{
@@ -1430,3 +1448,4 @@ inetname(struct in_addr *inp)
}
return (line);
}
+#endif
diff --git a/libbsd.py b/libbsd.py
index 3dd33081..21798bfe 100644
--- a/libbsd.py
+++ b/libbsd.py
@@ -1643,6 +1643,7 @@ class net(builder.Module):
'sys/net/ethernet.h',
'sys/net/firewire.h',
'sys/net/ieee8023ad_lacp.h',
+ 'sys/net/ieee_oui.h',
'sys/net/if_arp.h',
'sys/net/if_bridgevar.h',
'sys/net/if_clone.h',
@@ -4445,17 +4446,22 @@ class usr_sbin_wpa_supplicant(builder.Module):
'contrib/wpa/src/ap/wpa_auth_i.h',
'contrib/wpa/src/common/ctrl_iface_common.h',
'contrib/wpa/src/common/defs.h',
+ 'contrib/wpa/src/common/dpp.h',
'contrib/wpa/src/common/eapol_common.h',
'contrib/wpa/src/common/gas.h',
+ 'contrib/wpa/src/common/gas_server.h',
'contrib/wpa/src/common/hw_features_common.h',
'contrib/wpa/src/common/ieee802_11_common.h',
'contrib/wpa/src/common/ieee802_11_defs.h',
+ 'contrib/wpa/src/common/ieee802_1x_defs.h',
+ 'contrib/wpa/src/common/ocv.h',
'contrib/wpa/src/common/qca-vendor.h',
'contrib/wpa/src/common/sae.h',
'contrib/wpa/src/common/version.h',
'contrib/wpa/src/common/wpa_common.h',
'contrib/wpa/src/common/wpa_ctrl.h',
'contrib/wpa/src/crypto/aes.h',
+ 'contrib/wpa/src/crypto/aes_siv.h',
'contrib/wpa/src/crypto/aes_wrap.h',
'contrib/wpa/src/crypto/crypto.h',
'contrib/wpa/src/crypto/dh_group5.h',
@@ -4466,10 +4472,12 @@ class usr_sbin_wpa_supplicant(builder.Module):
'contrib/wpa/src/crypto/sha256.h',
'contrib/wpa/src/crypto/sha256_i.h',
'contrib/wpa/src/crypto/sha384.h',
+ 'contrib/wpa/src/crypto/sha512.h',
'contrib/wpa/src/crypto/tls.h',
'contrib/wpa/src/drivers/driver.h',
'contrib/wpa/src/drivers/driver_ndis.h',
'contrib/wpa/src/drivers/driver_nl80211.h',
+ 'contrib/wpa/src/drivers/driver_wired_common.h',
'contrib/wpa/src/drivers/linux_defines.h',
'contrib/wpa/src/eap_common/chap.h',
'contrib/wpa/src/eap_common/eap_common.h',
@@ -4496,7 +4504,6 @@ class usr_sbin_wpa_supplicant(builder.Module):
'contrib/wpa/src/l2_packet/l2_packet.h',
'contrib/wpa/src/p2p/p2p.h',
'contrib/wpa/src/radius/radius.h',
- 'contrib/wpa/src/rsn_supp/peerkey.h',
'contrib/wpa/src/rsn_supp/pmksa_cache.h',
'contrib/wpa/src/rsn_supp/preauth.h',
'contrib/wpa/src/rsn_supp/wpa.h',
@@ -4509,6 +4516,7 @@ class usr_sbin_wpa_supplicant(builder.Module):
'contrib/wpa/src/utils/bitfield.h',
'contrib/wpa/src/utils/build_config.h',
'contrib/wpa/src/utils/common.h',
+ 'contrib/wpa/src/utils/const_time.h',
'contrib/wpa/src/utils/eloop.h',
'contrib/wpa/src/utils/ext_password.h',
'contrib/wpa/src/utils/includes.h',
@@ -4547,7 +4555,7 @@ class usr_sbin_wpa_supplicant(builder.Module):
'contrib/wpa/wpa_supplicant/ctrl_iface.h',
'contrib/wpa/wpa_supplicant/dbus/dbus_common.h',
'contrib/wpa/wpa_supplicant/dbus/dbus_new.h',
- 'contrib/wpa/wpa_supplicant/dbus/dbus_old.h',
+ 'contrib/wpa/wpa_supplicant/dpp_supplicant.h',
'contrib/wpa/wpa_supplicant/driver_i.h',
'contrib/wpa/wpa_supplicant/gas_query.h',
'contrib/wpa/wpa_supplicant/hs20_supplicant.h',
@@ -4588,10 +4596,12 @@ class usr_sbin_wpa_supplicant(builder.Module):
'contrib/wpa/wpa_supplicant/main.c',
'contrib/wpa/wpa_supplicant/notify.c',
'contrib/wpa/wpa_supplicant/offchannel.c',
+ 'contrib/wpa/wpa_supplicant/op_classes.c',
+ 'contrib/wpa/wpa_supplicant/rrm.c',
'contrib/wpa/wpa_supplicant/scan.c',
'contrib/wpa/wpa_supplicant/wmm_ac.c',
- 'contrib/wpa/wpa_supplicant/wpa_supplicant.c',
'contrib/wpa/wpa_supplicant/wpas_glue.c',
+ 'contrib/wpa/wpa_supplicant/wpa_supplicant.c',
'contrib/wpa/wpa_supplicant/wps_supplicant.c',
'contrib/wpa/src/ap/ap_drv_ops.c',
'contrib/wpa/src/ap/hs20.c',
@@ -4599,6 +4609,7 @@ class usr_sbin_wpa_supplicant(builder.Module):
'contrib/wpa/src/ap/wpa_auth.c',
'contrib/wpa/src/ap/wpa_auth_ft.c',
'contrib/wpa/src/utils/base64.c',
+ 'contrib/wpa/src/utils/bitfield.c',
'contrib/wpa/src/utils/common.c',
'contrib/wpa/src/utils/eloop.c',
'contrib/wpa/src/utils/os_unix.c',
@@ -4614,6 +4625,7 @@ class usr_sbin_wpa_supplicant(builder.Module):
'contrib/wpa/src/drivers/driver_common.c',
'contrib/wpa/src/drivers/driver_ndis.c',
'contrib/wpa/src/drivers/driver_wired.c',
+ 'contrib/wpa/src/drivers/driver_wired_common.c',
'contrib/wpa/src/drivers/drivers.c',
'contrib/wpa/src/wps/http_client.c',
'contrib/wpa/src/wps/http_server.c',
@@ -4633,7 +4645,6 @@ class usr_sbin_wpa_supplicant(builder.Module):
'contrib/wpa/src/wps/wps_upnp_ssdp.c',
'contrib/wpa/src/wps/wps_upnp_web.c',
'contrib/wpa/src/l2_packet/l2_packet_freebsd.c',
- 'contrib/wpa/src/rsn_supp/peerkey.c',
'contrib/wpa/src/rsn_supp/pmksa_cache.c',
'contrib/wpa/src/rsn_supp/preauth.c',
'contrib/wpa/src/rsn_supp/wpa.c',
diff --git a/rtemsbsd/include/machine/rtems-bsd-kernel-namespace.h b/rtemsbsd/include/machine/rtems-bsd-kernel-namespace.h
index 30272306..bcf195af 100644
--- a/rtemsbsd/include/machine/rtems-bsd-kernel-namespace.h
+++ b/rtemsbsd/include/machine/rtems-bsd-kernel-namespace.h
@@ -358,7 +358,6 @@
#define bridge_control_table_size _bsd_bridge_control_table_size
#define bridge_dn_p _bsd_bridge_dn_p
#define bridge_rtable_prune_period _bsd_bridge_rtable_prune_period
-#define bridge_rtnode_zone _bsd_bridge_rtnode_zone
#define bstp_attach _bsd_bstp_attach
#define bstp_create _bsd_bstp_create
#define bstp_destroy _bsd_bstp_destroy
@@ -462,6 +461,8 @@
#define bus_get_resource _bsd_bus_get_resource
#define bus_get_resource_count _bsd_bus_get_resource_count
#define bus_get_resource_start _bsd_bus_get_resource_start
+#define bus_helper_reset_post _bsd_bus_helper_reset_post
+#define bus_helper_reset_prepare _bsd_bus_helper_reset_prepare
#define bus_map_resource _bsd_bus_map_resource
#define bus_null_rescan _bsd_bus_null_rescan
#define bus_print_child_domain _bsd_bus_print_child_domain
@@ -1139,6 +1140,7 @@
#define ether_crc32_be _bsd_ether_crc32_be
#define ether_crc32_le _bsd_ether_crc32_le
#define ether_demux _bsd_ether_demux
+#define ether_gen_addr _bsd_ether_gen_addr
#define ether_ifattach _bsd_ether_ifattach
#define ether_ifdetach _bsd_ether_ifdetach
#define ether_ioctl _bsd_ether_ioctl
@@ -1326,7 +1328,9 @@
#define gre_hashdestroy _bsd_gre_hashdestroy
#define gre_hashinit _bsd_gre_hashinit
#define gre_input _bsd_gre_input
-#define gre_updatehdr _bsd_gre_updatehdr
+#define gre_sofree _bsd_gre_sofree
+#define gre_update_hdr _bsd_gre_update_hdr
+#define gre_update_udphdr _bsd_gre_update_udphdr
#define grouptask_block _bsd_grouptask_block
#define grouptaskqueue_enqueue _bsd_grouptaskqueue_enqueue
#define grouptask_unblock _bsd_grouptask_unblock
@@ -3101,6 +3105,7 @@
#define pci_ea_is_enabled _bsd_pci_ea_is_enabled
#define pcie_flr _bsd_pcie_flr
#define pcie_get_max_completion_timeout _bsd_pcie_get_max_completion_timeout
+#define pcie_link_reset _bsd_pcie_link_reset
#define pci_enable_busmaster_method _bsd_pci_enable_busmaster_method
#define pci_enable_io_method _bsd_pci_enable_io_method
#define pci_enable_msi_method _bsd_pci_enable_msi_method
@@ -3140,6 +3145,7 @@
#define pci_msix_table_bar_method _bsd_pci_msix_table_bar_method
#define pci_numdevs _bsd_pci_numdevs
#define pci_pending_msix _bsd_pci_pending_msix
+#define pci_power_reset _bsd_pci_power_reset
#define pci_print_child _bsd_pci_print_child
#define pci_print_faulted_dev _bsd_pci_print_faulted_dev
#define pci_print_verbose _bsd_pci_print_verbose
@@ -4882,6 +4888,7 @@
#define tcp_recvspace _bsd_tcp_recvspace
#define tcp_respond _bsd_tcp_respond
#define tcp_rexmit_drop_options _bsd_tcp_rexmit_drop_options
+#define tcp_rexmit_initial _bsd_tcp_rexmit_initial
#define tcp_rexmit_min _bsd_tcp_rexmit_min
#define tcp_rexmit_slop _bsd_tcp_rexmit_slop
#define tcprexmtthresh _bsd_tcprexmtthresh
@@ -4902,7 +4909,6 @@
#define tcpstat _bsd_tcpstat
#define tcp_state_change _bsd_tcp_state_change
#define tcp_switch_back_to_default _bsd_tcp_switch_back_to_default
-#define tcp_syn_backoff _bsd_tcp_syn_backoff
#define tcp_timer_2msl _bsd_tcp_timer_2msl
#define tcp_timer_activate _bsd_tcp_timer_activate
#define tcp_timer_active _bsd_tcp_timer_active
diff --git a/rtemsbsd/include/rtems/bsd/local/bus_if.h b/rtemsbsd/include/rtems/bsd/local/bus_if.h
index cc15dcad..1e54621f 100644
--- a/rtemsbsd/include/rtems/bsd/local/bus_if.h
+++ b/rtemsbsd/include/rtems/bsd/local/bus_if.h
@@ -1155,4 +1155,75 @@ static __inline int BUS_GET_CPUS(device_t _dev, device_t _child,
return (rc);
}
+/** @brief Unique descriptor for the BUS_RESET_PREPARE() method */
+extern struct kobjop_desc bus_reset_prepare_desc;
+/** @brief A function implementing the BUS_RESET_PREPARE() method */
+typedef int bus_reset_prepare_t(device_t _dev, device_t _child);
+/**
+ * @brief Prepares the given child of the bus for reset
+ *
+ * Typically bus detaches or suspends children' drivers, and then
+ * calls this method to save bus-specific information, for instance,
+ * PCI config space, which is damaged by reset.
+ *
+ * The bus_helper_reset_prepare() helper is provided to ease
+ * implementing bus reset methods.
+ *
+ * @param _dev the bus device
+ * @param _child the child device
+ */
+
+static __inline int BUS_RESET_PREPARE(device_t _dev, device_t _child)
+{
+ kobjop_t _m;
+ int rc;
+ KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_reset_prepare);
+ rc = ((bus_reset_prepare_t *) _m)(_dev, _child);
+ return (rc);
+}
+
+/** @brief Unique descriptor for the BUS_RESET_POST() method */
+extern struct kobjop_desc bus_reset_post_desc;
+/** @brief A function implementing the BUS_RESET_POST() method */
+typedef int bus_reset_post_t(device_t _dev, device_t _child);
+/**
+ * @brief Restores the child operations after the reset
+ *
+ * The bus_helper_reset_post() helper is provided to ease
+ * implementing bus reset methods.
+ *
+ * @param _dev the bus device
+ * @param _child the child device
+ */
+
+static __inline int BUS_RESET_POST(device_t _dev, device_t _child)
+{
+ kobjop_t _m;
+ int rc;
+ KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_reset_post);
+ rc = ((bus_reset_post_t *) _m)(_dev, _child);
+ return (rc);
+}
+
+/** @brief Unique descriptor for the BUS_RESET_CHILD() method */
+extern struct kobjop_desc bus_reset_child_desc;
+/** @brief A function implementing the BUS_RESET_CHILD() method */
+typedef int bus_reset_child_t(device_t _dev, device_t _child, int _flags);
+/**
+ * @brief Performs reset of the child
+ *
+ * @param _dev the bus device
+ * @param _child the child device
+ * @param _flags DEVF_RESET_ flags
+ */
+
+static __inline int BUS_RESET_CHILD(device_t _dev, device_t _child, int _flags)
+{
+ kobjop_t _m;
+ int rc;
+ KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_reset_child);
+ rc = ((bus_reset_child_t *) _m)(_dev, _child, _flags);
+ return (rc);
+}
+
#endif /* _bus_if_h_ */
diff --git a/rtemsbsd/include/rtems/bsd/local/usbdevs.h b/rtemsbsd/include/rtems/bsd/local/usbdevs.h
index 73904347..ce66071e 100644
--- a/rtemsbsd/include/rtems/bsd/local/usbdevs.h
+++ b/rtemsbsd/include/rtems/bsd/local/usbdevs.h
@@ -356,6 +356,7 @@
#define USB_VENDOR_AGFA 0x06bd /* AGFA-Gevaert */
#define USB_VENDOR_ASIAMD 0x06be /* Asia Microelectronic Development */
#define USB_VENDOR_BIZLINK 0x06c4 /* Bizlink International */
+#define USB_VENDOR_SYNAPTICS 0x06cb /* Synaptics, Inc. */
#define USB_VENDOR_KEYSPAN 0x06cd /* Keyspan / InnoSys Inc. */
#define USB_VENDOR_CONTEC 0x06ce /* Contec products */
#define USB_VENDOR_AASHIMA 0x06d6 /* Aashima Technology */
@@ -2587,6 +2588,7 @@
#define USB_PRODUCT_INTEL2_IRMH2 0x0024 /* Integrated Rate Matching Hub */
#define USB_PRODUCT_INTEL2_IRMH3 0x8000 /* Integrated Rate Matching Hub */
#define USB_PRODUCT_INTEL2_IRMH4 0x8008 /* Integrated Rate Matching Hub */
+#define USB_PRODUCT_INTEL2_SNP 0x0a2b /* Stone Peak (7265) Bluetooth Module */
#define USB_PRODUCT_INTEL2_SFP 0x0aa7 /* Sandy Peak (3168) Bluetooth Module */
#define USB_PRODUCT_INTEL2_JFP 0x0aaa /* Jefferson Peak (9460/9560) Bluetooth Module */
#define USB_PRODUCT_INTEL2_THP 0x0025 /* Thunder Peak (9160/9260) Bluetooth Module */
@@ -2679,6 +2681,9 @@
#define USB_PRODUCT_KENSINGTON_ORBIT 0x1003 /* Orbit USB/PS2 trackball */
#define USB_PRODUCT_KENSINGTON_TURBOBALL 0x1005 /* TurboBall */
+/* Synaptics products */
+#define USB_PRODUCT_SYNAPTICS_FPR9A 0x009a /* Fingerprint Reader */
+
/* Keyspan products */
#define USB_PRODUCT_KEYSPAN_USA28_NF 0x0101 /* USA-28 serial Adapter (no firmware) */
#define USB_PRODUCT_KEYSPAN_USA28X_NF 0x0102 /* USA-28X serial Adapter (no firmware) */
diff --git a/rtemsbsd/include/rtems/bsd/local/usbdevs_data.h b/rtemsbsd/include/rtems/bsd/local/usbdevs_data.h
index aa199490..78e9bb1b 100644
--- a/rtemsbsd/include/rtems/bsd/local/usbdevs_data.h
+++ b/rtemsbsd/include/rtems/bsd/local/usbdevs_data.h
@@ -8054,6 +8054,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"Integrated Rate Matching Hub",
},
{
+ USB_VENDOR_INTEL2, USB_PRODUCT_INTEL2_SNP,
+ 0,
+ "Intel",
+ "Stone Peak (7265) Bluetooth Module",
+ },
+ {
USB_VENDOR_INTEL2, USB_PRODUCT_INTEL2_SFP,
0,
"Intel",
@@ -8372,6 +8378,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"TurboBall",
},
{
+ USB_VENDOR_SYNAPTICS, USB_PRODUCT_SYNAPTICS_FPR9A,
+ 0,
+ "Synaptics, Inc.",
+ "Fingerprint Reader",
+ },
+ {
USB_VENDOR_KEYSPAN, USB_PRODUCT_KEYSPAN_USA28_NF,
0,
"Keyspan / InnoSys Inc.",
@@ -20792,6 +20804,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_SYNAPTICS, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Synaptics, Inc.",
+ NULL,
+ },
+ {
USB_VENDOR_KEYSPAN, 0,
USB_KNOWNDEV_NOPROD,
"Keyspan / InnoSys Inc.",
diff --git a/rtemsbsd/local/bus_if.c b/rtemsbsd/local/bus_if.c
index 4b679f43..789aed0c 100644
--- a/rtemsbsd/local/bus_if.c
+++ b/rtemsbsd/local/bus_if.c
@@ -47,6 +47,16 @@ null_add_child(device_t bus, int order, const char *name,
panic("bus_add_child is not implemented");
}
+static int null_reset_post(device_t bus, device_t dev)
+{
+ return (0);
+}
+
+static int null_reset_prepare(device_t bus, device_t dev)
+{
+ return (0);
+}
+
struct kobjop_desc bus_print_child_desc = {
0, { &bus_print_child_desc, (kobjop_t)bus_generic_print_child }
};
@@ -207,3 +217,15 @@ struct kobjop_desc bus_get_cpus_desc = {
0, { &bus_get_cpus_desc, (kobjop_t)bus_generic_get_cpus }
};
+struct kobjop_desc bus_reset_prepare_desc = {
+ 0, { &bus_reset_prepare_desc, (kobjop_t)null_reset_prepare }
+};
+
+struct kobjop_desc bus_reset_post_desc = {
+ 0, { &bus_reset_post_desc, (kobjop_t)null_reset_post }
+};
+
+struct kobjop_desc bus_reset_child_desc = {
+ 0, { &bus_reset_child_desc, (kobjop_t)kobj_error_method }
+};
+